home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 2
/
Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso
/
Aminet
/
text
/
print
/
ghostscript2_6_1.lha
/
amiga-src
/
gdevamiga.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-25
|
110KB
|
5,239 lines
/* Copyright (C) 1992 Aladdin Enterprises. All rights reserved.
Distributed by Free Software Foundation, Inc.
This file is part of Ghostscript.
Ghostscript is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
to anyone for the consequences of using it or for whether it serves any
particular purpose or works at all, unless he says so in writing. Refer
to the Ghostscript General Public License for full details.
Everyone is granted permission to copy, modify and redistribute
Ghostscript, but only under the conditions described in the Ghostscript
General Public License. A copy of this license is supposed to have been
given to you along with Ghostscript so you can know your rights and
responsibilities. It should be in a file named COPYING. Among other
things, the copyright notice and this notice must be preserved on all
copies. */
/* gdevamiga.c */
/* Amiga driver for Ghostscript library, requires Kickstart 2.04 or higher */
/* Written by Olaf `Olsen' Barthel, last change 25 July 1993
*
* My address: Olaf Barthel
* Brabeckstrasse 35
* D-30559 Hannover
*
* eMail: olsen@sourcery.han.de
*/
#include <intuition/intuitionbase.h>
#include <intuition/gadgetclass.h>
#include <intuition/imageclass.h>
#include <intuition/icclass.h>
#include <graphics/displayinfo.h>
#include <libraries/iffparse.h>
#include <graphics/gfxbase.h>
#include <devices/printer.h>
#include <devices/prtbase.h>
#include <devices/prtgfx.h>
#include <exec/memory.h>
#include <clib/macros.h>
#include <dos/dostags.h>
#include <dos/rdargs.h>
#include <dos/dos.h>
#include <inline/stubs.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/layers_protos.h>
/*
#include <clib/utility_protos.h>
#include <clib/exec_protos.h>
*/
#include <inline/iffparse.h>
#include <inline/utility.h>
#include <inline/exec.h>
#include <inline/dos.h>
#define ushort foo
#include <string.h>
#include <signal.h>
#undef ushort
#include "gx.h" /* for gx_bitmap; includes std.h */
#include "gsmatrix.h" /* needed for gxdevice.h */
#include "gxdevice.h"
#include "gserrors.h"
#include "gsprops.h"
/* Here is how to select a default page size format:
*
* Either enter include a line such as
*
* #define AMIGA_PAGE_A4 1
*
* Somewhere above in this module, or edit the makefile
* to feature the option
*
* -dAMIGA_PAGE_A4
*
* among the device specific flags. Available default page
* size formats are:
*
* AMIGA_PAGE_A4 European A4 page size (default)
* AMIGA_PAGE_LETTER US letter page size
* AMIGA_PAGE_LEGAL US legal page size
* AMIGA_PAGE_LEDGER US ledger paper size
* AMIGA_PAGE_TABLOID US tabloid paper size
*/
/* Select the default paper size if none specified. */
#if !defined(AMIGA_PAGE_A4) && !defined(AMIGA_PAGE_LETTER) && !defined(AMIGA_PAGE_LEGAL) && !defined(AMIGA_PAGE_LEDGER) && !defined(AMIGA_PAGE_TABLOID)
#define AMIGA_PAGE_A4 1
#endif /* PAGE SIZE */
/* A4 page size (in inches!) */
#ifdef AMIGA_PAGE_A4
#define DEFAULT_WIDTH 8.2
#define DEFAULT_HEIGHT 11.6
#endif /* AMIGA_PAGE_A4 */
/* US letter page size */
#ifdef AMIGA_PAGE_LETTER
#define DEFAULT_WIDTH 8.5
#define DEFAULT_HEIGHT 11.0
#endif /* AMIGA_PAGE_LETTER */
/* US legal page size */
#ifdef AMIGA_PAGE_LEGAL
#define DEFAULT_WIDTH 8.5
#define DEFAULT_HEIGHT 14.0
#endif /* AMIGA_PAGE_LEGAL */
/* US ledger page size */
#ifdef AMIGA_PAGE_LEDGER
#define DEFAULT_WIDTH 16.0
#define DEFAULT_HEIGHT 11.0
#endif /* AMIGA_PAGE_LEDGER */
/* US tabloid page size */
#ifdef AMIGA_PAGE_TABLOID
#define DEFAULT_WIDTH 11.0
#define DEFAULT_HEIGHT 17.0
#endif /* AMIGA_PAGE_LEDGER */
/* Default output file name. */
#define DEFAULT_FILENAME "gs_page"
/* Turn a byte into a 24 bit colour value. */
#define SPREAD(i) ((ULONG)(i) << 24 | (ULONG)(i) << 16 | (ULONG)(i) << 8 | (i))
/* Scroller gadget IDs. */
enum { VERTICAL_SCROLLER, HORIZONTAL_SCROLLER,
UP_ARROW, DOWN_ARROW,
LEFT_ARROW, RIGHT_ARROW,
GADGET_COUNT };
/* Scroller arrow IDs. */
enum { UP_IMAGE, DOWN_IMAGE,
LEFT_IMAGE, RIGHT_IMAGE,
IMAGE_COUNT };
/* Codes for the MoveAround() routine. */
enum { MOVE_MIN,MOVE_FAR_DOWN,MOVE_DOWN,MOVE_UP,MOVE_FAR_UP,MOVE_MAX };
/* Some handy bit masks. */
#define SIG_KILL SIGBREAKF_CTRL_C
#define SIG_HANDSHAKE SIGF_SINGLE
/* Static dimensions of scroller arrows. */
#define ARROW_WIDTH 16
#define ARROW_HEIGHT 11
/* The `Help' key raw code. */
#define HELP_CODE 95
/* Minimum window inner area dimension. */
#define MINIMUM_WIDTH 64
#define MINIMUM_HEIGHT 32
/* Handy superbitmap window macros. */
#define LAYERXOFFSET(w) ((w) -> RPort -> Layer -> Scroll_X)
#define LAYERYOFFSET(w) ((w) -> RPort -> Layer -> Scroll_Y)
/* User input to listen to. */
#define IDCMP_FLAGS (IDCMP_IDCMPUPDATE | IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_MOUSEMOVE | IDCMP_NEWSIZE | IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | IDCMP_RAWKEY)
/* Chunk IDs. */
#define ID_ILBM MAKE_ID('I','L','B','M')
#define ID_BMHD MAKE_ID('B','M','H','D')
#define ID_CMAP MAKE_ID('C','M','A','P')
#define ID_CAMG MAKE_ID('C','A','M','G')
#define ID_ANNO MAKE_ID('A','N','N','O')
#define ID_DPI MAKE_ID('D','P','I',' ')
#define ID_BODY MAKE_ID('B','O','D','Y')
/* Chunk contents definitions. */
typedef struct
{
UWORD w,h; /* raster width & height in pixels */
WORD x,y; /* position for this image */
UBYTE nPlanes; /* # source bitplanes */
UBYTE masking; /* masking technique */
UBYTE compression; /* compression algoithm */
UBYTE pad1; /* UNUSED. For consistency, put 0 here.*/
UWORD transparentColor; /* transparent "color number" */
UBYTE xAspect,yAspect; /* aspect ratio, a rational number x/y */
WORD pageWidth,pageHeight; /* source "page" size in pixels */
} BitMapHeader;
typedef struct
{
UWORD dpi_x;
UWORD dpi_y;
} DPIHeader;
/* Packer modes. */
#define DUMP 0
#define RUN 1
/* Minimum data run size, maximum data run size and maximum cache size. */
#define MINRUN 3
#define MAXRUN 128
#define MAXDAT 128
/* This module actually implements four different Amiga based
* devices. As the rendering operations are all the same,
* one single device definition is sufficient.
*/
typedef struct gx_device_amiga
{
gx_device_common;
struct Screen *screen; /* Any screen */
struct Window *window; /* Some window to be opened on the Workbench screen */
LONG super_width, /* Superbitmap width */
super_height; /* Superbitmap height */
struct BitMap *super_bitmap; /* Window superbitmap area */
struct Gadget **gadget; /* Scroller gadgets */
struct Image **image; /* Scroller arrow images */
struct Task *dispatcher; /* Slider dispatch task */
struct Process *main; /* Main program */
struct RastPort *rport; /* Rendering area */
struct IODRPReq *printer; /* Printer interface data */
struct MsgPort *port; /* Printer io data */
struct ColorMap *colormap; /* A black/white colour map */
struct BitMap *bitmap; /* Rendering bitmap data */
PLANEPTR bitplane; /* Rendering raster */
gx_color_index last_pen; /* The last colour set */
float page_width, /* The page width */
page_height; /* The page height */
char file_name[256];/* The output file name */
int page_count; /* The page number counter */
int cube_size; /* Colour cube size, 0 for b/w */
struct RastPort *temp_rport; /* Temporary raster port for pixmap imaging. */
UBYTE *temp_array; /* Temporary colour manipulation array. */
LONG *pens;
} gx_device_amiga;
/* Function prototypes */
VOID set_mono_device(gx_device_amiga *dev);
VOID set_colour_device(gx_device_amiga *dev,int cube_size,LONG *pens);
VOID set_colour_printer_device(gx_device_amiga *dev,LONG CubeSize);
VOID DeleteBitMap(struct BitMap *BitMap,BOOL Private);
struct BitMap * CreateBitMap(LONG Width,LONG Height,LONG Depth,ULONG Flags,struct BitMap *Friend,BOOL Private);
VOID DeleteTempRPort(struct RastPort *Temp);
struct RastPort * CreateTempRPort(struct RastPort *Source);
LONG Euclid(LONG a,LONG b);
BYTE * PutDump(register BYTE *Destination,register LONG Count);
BYTE * PutRun(register BYTE *Destination,LONG Count,WORD Char);
LONG PackRow(PLANEPTR *SourcePtr,register BYTE *Destination,LONG RowSize);
BOOL PutBODY(struct IFFHandle *Handle,struct BitMap *BitMap);
BOOL PutANNO(struct IFFHandle *Handle);
BOOL PutCAMG(struct IFFHandle *Handle);
BOOL PutCMAP(struct IFFHandle *Handle);
BOOL PutDPI(struct IFFHandle *Handle,UWORD X_DPI,UWORD Y_DPI);
BOOL PutBMHD(struct IFFHandle *Handle,LONG Width,LONG Height,UWORD X_DPI,UWORD Y_DPI);
BOOL SaveBitMap(STRPTR Name,struct BitMap *BitMap,LONG Width,LONG Height,UWORD X_DPI,UWORD Y_DPI);
float GetInches(STRPTR Buffer);
VOID DispatchTask(VOID);
VOID DeleteScrollers(gx_device *dev);
BOOL CreateScrollers(gx_device *dev,struct Screen *Screen);
VOID WindowResize(gx_device *dev);
VOID WindowUpdate(struct Gadget *Gadget,gx_device *dev);
VOID MoveAround(struct Gadget *Gadget,LONG How,gx_device *dev);
VOID DispatchSuperWindow(gx_device *dev);
void devcleanup(VOID);
gx_color_index amiga_map_rgb_color(gx_device *dev,gx_color_value red,gx_color_value green,gx_color_value blue);
int amiga_map_color_rgb(gx_device *dev,gx_color_index color,gx_color_value rgb[3]);
LONG * AllocatePens(struct ViewPort *VPort,LONG CubeSize);
int amiga_open_default(gx_device *dev);
int amiga_open_low(gx_device *dev);
int amiga_open_high(gx_device *dev);
int amiga_open_super(gx_device *dev);
int amiga_open_a2024(gx_device *dev);
int amiga_open_printer(gx_device *dev);
int amiga_output_page_printer(gx_device *dev,int num_copies,int flush);
int amiga_close_printer(gx_device *dev);
int amiga_get_bits(gx_device *dev,int y,byte *str,byte **actual_data);
int amiga_open(gx_device *dev,ULONG Mode);
int amiga_output_page(gx_device *dev,int num_copies,int flush);
int amiga_close(gx_device *dev);
int amiga_fill_rectangle(gx_device *dev,int x,int y,int w,int h,gx_color_index color);
int amiga_copy_mono(gx_device *dev,const UBYTE *base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one);
int amiga_copy_color(gx_device *dev,const UBYTE *base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h);
int amiga_draw_line(gx_device *dev,int x0,int y0,int x1,int y1,gx_color_index color);
int amiga_copy_mono_raw(gx_device *dev,const UBYTE *base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one);
int amiga_copy_color_raw(gx_device *dev,const UBYTE *base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h);
int amiga_fill_rectangle_raw(gx_device *dev,int x,int y,int w,int h,gx_color_index color);
int amiga_draw_line_raw(gx_device *dev,int x,int y,int x1,int y1,gx_color_index color);
int amiga_open_ilbm(gx_device *dev);
int amiga_output_page_ilbm(gx_device *dev,int num_copies,int flush);
int amiga_close_ilbm(gx_device *dev);
int amiga_get_props(gx_device *dev,gs_prop_item *plist);
int amiga_put_props(gx_device *dev,gs_prop_item *plist,int count);
gx_color_index amiga_color_map_rgb_color(gx_device *dev,gx_color_value red,gx_color_value green,gx_color_value blue);
int amiga_color_map_color_rgb(gx_device *dev,gx_color_index color,gx_color_value rgb[3]);
gx_color_index amiga_color_map_rgb_color_pen(gx_device *dev,gx_color_value red,gx_color_value green,gx_color_value blue);
int amiga_color_map_color_rgb_pen(gx_device *dev,gx_color_index color,gx_color_value rgb[3]);
int amiga_copy_color8(gx_device *dev,const UBYTE *base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h);
int amiga_copy_mono_raw_color(gx_device *dev,const UBYTE *base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one);
int amiga_copy_color_raw_color16(gx_device *dev,const UBYTE *data,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h);
int amiga_fill_rectangle_raw_color(gx_device *dev,int x,int y,int w,int h,gx_color_index color);
int amiga_draw_line_raw_color(gx_device *dev,int x,int y,int x1,int y1,gx_color_index color);
/* External reference to graphics.library, required for version checking. */
extern struct GfxBase *GfxBase;
/* Number of packed bytes and pack buffer. */
LONG PackedBytes;
BYTE Buffer[MAXDAT + 1];
/* Resolutions associated with display modes. Note: these values
* have been determined empirically using an A2024 monitor.
* In essence, your mileage may vary. This table only gives the
* horizontal resolution and relies on the graphics display
* data base to give the corresponding vertical resolution
* (through aspect/ratio information).
*
* Not all screen and printer resolutions will be large enough
* to hold the contents of a Ghostscript page (whose size appears
* to be hard-coded into the corresponding file), so you may want
* to use the "scale" operator to make it fit (I suggest something
* like "0.7 dup scale" for screen output).
*/
STATIC struct { ULONG mode; float dpi; } mode_dpi_table[4] =
{
A2024_MONITOR_ID, 100.0, /* 1..1024, requires A2024 or Viking monitor */
SUPER_KEY, 130.0, /* 1..1280, 35 nS */
HIRES_KEY, 70.0, /* 1.. 640, 70 nS */
LORES_KEY, 35.0 /* 1.. 320, 140 nS */
};
/* Bit masks. */
STATIC UBYTE shift[8] = { 128, 64, 32, 16, 8, 4, 2, 1 },
masks[8] = { 127,191,223,239,247,251,253,254 };
/* Device routine jump tables */
STATIC gx_device_procs amiga_default_procs =
{
amiga_open_default,
gx_default_get_initial_matrix,
gx_default_sync_output,
amiga_output_page,
amiga_close,
amiga_map_rgb_color,
amiga_map_color_rgb,
amiga_fill_rectangle,
gx_default_tile_rectangle,
amiga_copy_mono,
amiga_copy_color,
amiga_draw_line,
gx_default_get_bits,
amiga_get_props,
amiga_put_props
};
STATIC gx_device_procs amiga_low_procs =
{
amiga_open_low,
gx_default_get_initial_matrix,
gx_default_sync_output,
amiga_output_page,
amiga_close,
amiga_map_rgb_color,
amiga_map_color_rgb,
amiga_fill_rectangle,
gx_default_tile_rectangle,
amiga_copy_mono,
amiga_copy_color,
amiga_draw_line,
gx_default_get_bits,
amiga_get_props,
amiga_put_props
};
STATIC gx_device_procs amiga_high_procs =
{
amiga_open_high,
gx_default_get_initial_matrix,
gx_default_sync_output,
amiga_output_page,
amiga_close,
amiga_map_rgb_color,
amiga_map_color_rgb,
amiga_fill_rectangle,
gx_default_tile_rectangle,
amiga_copy_mono,
amiga_copy_color,
amiga_draw_line,
gx_default_get_bits,
amiga_get_props,
amiga_put_props
};
STATIC gx_device_procs amiga_super_procs =
{
amiga_open_super,
gx_default_get_initial_matrix,
gx_default_sync_output,
amiga_output_page,
amiga_close,
amiga_map_rgb_color,
amiga_map_color_rgb,
amiga_fill_rectangle,
gx_default_tile_rectangle,
amiga_copy_mono,
amiga_copy_color,
amiga_draw_line,
gx_default_get_bits,
amiga_get_props,
amiga_put_props
};
STATIC gx_device_procs amiga_a2024_procs =
{
amiga_open_a2024,
gx_default_get_initial_matrix,
gx_default_sync_output,
amiga_output_page,
amiga_close,
amiga_map_rgb_color,
amiga_map_color_rgb,
amiga_fill_rectangle,
gx_default_tile_rectangle,
amiga_copy_mono,
amiga_copy_color,
amiga_draw_line,
gx_default_get_bits,
amiga_get_props,
amiga_put_props
};
STATIC gx_device_procs amiga_printer_procs =
{
amiga_open_printer,
gx_default_get_initial_matrix,
gx_default_sync_output,
amiga_output_page_printer,
amiga_close_printer,
amiga_map_rgb_color,
amiga_map_color_rgb,
amiga_fill_rectangle_raw,
gx_default_tile_rectangle,
amiga_copy_mono_raw,
amiga_copy_color_raw,
amiga_draw_line_raw,
amiga_get_bits,
amiga_get_props,
amiga_put_props
};
STATIC gx_device_procs amiga_ilbm_procs =
{
amiga_open_ilbm,
gx_default_get_initial_matrix,
gx_default_sync_output,
amiga_output_page_ilbm,
amiga_close_ilbm,
amiga_map_rgb_color,
amiga_map_color_rgb,
amiga_fill_rectangle_raw,
gx_default_tile_rectangle,
amiga_copy_mono_raw,
amiga_copy_color_raw,
amiga_draw_line_raw,
amiga_get_bits,
amiga_get_props,
amiga_put_props
};
/* Default device: opens a window on the Workbench screen and renders into it */
gx_device_amiga gs_amiga_device =
{
sizeof(gx_device_amiga), /* params_size */
&amiga_default_procs, /* procs */
"amiga", /* dname */
0, 0, /* width, height */
72.27, 72.27, /* xdpi, ydpi */
no_margins, /* margins */
dci_black_and_white, /* color info */
0, /* is_open */
NULL, /* screen */
NULL, /* window */
0, /* super_width */
0, /* super_height */
NULL, /* super_bitmap */
NULL, /* gadget */
NULL, /* image */
NULL, /* dispatcher */
NULL, /* main */
NULL, /* rport */
NULL, /* printer */
NULL, /* port */
NULL, /* colormap */
NULL, /* bitmap */
NULL, /* bitplane */
1, /* last_pen */
DEFAULT_WIDTH, /* page width */
DEFAULT_HEIGHT, /* page height */
DEFAULT_FILENAME, /* output file */
1, /* page counter */
0, /* cube_size */
NULL, /* temp_rport */
NULL, /* temp_array */
NULL /* pens */
};
/* Low resolution device: opens a lores custom screen and renders into it */
gx_device_amiga gs_amiga_low_device =
{
sizeof(gx_device_amiga), /* params_size */
&amiga_low_procs, /* procs */
"amiga_low", /* dname */
0, 0, /* width, height */
72.27, 72.27, /* xdpi, ydpi */
no_margins, /* margins */
dci_black_and_white, /* color info */
0, /* is_open */
NULL, /* screen */
NULL, /* window */
0, /* super_width */
0, /* super_height */
NULL, /* super_bitmap */
NULL, /* gadget */
NULL, /* image */
NULL, /* dispatcher */
NULL, /* main */
NULL, /* rport */
NULL, /* printer */
NULL, /* port */
NULL, /* colormap */
NULL, /* bitmap */
NULL, /* bitplane */
1, /* last_pen */
DEFAULT_WIDTH, /* page width */
DEFAULT_HEIGHT, /* page height */
DEFAULT_FILENAME, /* output file */
1, /* page counter */
0, /* cube_size */
NULL, /* temp_rport */
NULL, /* temp_array */
NULL /* pens */
};
/* High resolution device: opens a highres-interlaced custom screen */
gx_device_amiga gs_amiga_high_device =
{
sizeof(gx_device_amiga), /* params_size */
&amiga_high_procs, /* procs */
"amiga_high", /* dname */
0, 0, /* width, height */
72.27, 72.27, /* xdpi, ydpi */
no_margins, /* margins */
dci_black_and_white, /* color info */
0, /* is_open */
NULL, /* screen */
NULL, /* window */
0, /* super_width */
0, /* super_height */
NULL, /* super_bitmap */
NULL, /* gadget */
NULL, /* image */
NULL, /* dispatcher */
NULL, /* main */
NULL, /* rport */
NULL, /* printer */
NULL, /* port */
NULL, /* colormap */
NULL, /* bitmap */
NULL, /* bitplane */
1, /* last_pen */
DEFAULT_WIDTH, /* page width */
DEFAULT_HEIGHT, /* page height */
DEFAULT_FILENAME, /* output file */
1, /* page counter */
0, /* cube_size */
NULL, /* temp_rport */
NULL, /* temp_array */
NULL /* pens */
};
/* Super high resolution device: opens a super-highres-interlaced custom screen */
gx_device_amiga gs_amiga_super_device =
{
sizeof(gx_device_amiga), /* params_size */
&amiga_super_procs, /* procs */
"amiga_super", /* dname */
0, 0, /* width, height */
72.27, 72.27, /* xdpi, ydpi */
no_margins, /* margins */
dci_black_and_white, /* color info */
0, /* is_open */
NULL, /* screen */
NULL, /* window */
0, /* super_width */
0, /* super_height */
NULL, /* super_bitmap */
NULL, /* gadget */
NULL, /* image */
NULL, /* dispatcher */
NULL, /* main */
NULL, /* rport */
NULL, /* printer */
NULL, /* port */
NULL, /* colormap */
NULL, /* bitmap */
NULL, /* bitplane */
1, /* last_pen */
DEFAULT_WIDTH, /* page width */
DEFAULT_HEIGHT, /* page height */
DEFAULT_FILENAME, /* output file */
1, /* page counter */
0, /* cube_size */
NULL, /* temp_rport */
NULL, /* temp_array */
NULL /* pens */
};
/* A2024 device: opens an A2024 custom screen */
gx_device_amiga gs_amiga_a2024_device =
{
sizeof(gx_device_amiga), /* params_size */
&amiga_a2024_procs, /* procs */
"amiga_a2024", /* dname */
0, 0, /* width, height */
72.27, 72.27, /* xdpi, ydpi */
no_margins, /* margins */
dci_black_and_white, /* color info */
0, /* is_open */
NULL, /* screen */
NULL, /* window */
0, /* super_width */
0, /* super_height */
NULL, /* super_bitmap */
NULL, /* gadget */
NULL, /* image */
NULL, /* dispatcher */
NULL, /* main */
NULL, /* rport */
NULL, /* printer */
NULL, /* port */
NULL, /* colormap */
NULL, /* bitmap */
NULL, /* bitplane */
1, /* last_pen */
DEFAULT_WIDTH, /* page width */
DEFAULT_HEIGHT, /* page height */
DEFAULT_FILENAME, /* output file */
1, /* page counter */
0, /* cube_size */
NULL, /* temp_rport */
NULL, /* temp_array */
NULL /* pens */
};
/* Printer device: renders the imagery and sends it to the printer */
gx_device_amiga gs_amiga_printer_device =
{
sizeof(gx_device_amiga), /* params_size */
&amiga_printer_procs, /* procs */
"amiga_printer", /* dname */
0, 0, /* width, height */
72.27, 72.27, /* xdpi, ydpi */
no_margins, /* margins */
dci_black_and_white, /* color info */
0, /* is_open */
NULL, /* screen */
NULL, /* window */
0, /* super_width */
0, /* super_height */
NULL, /* super_bitmap */
NULL, /* gadget */
NULL, /* image */
NULL, /* dispatcher */
NULL, /* main */
NULL, /* rport */
NULL, /* printer */
NULL, /* port */
NULL, /* colormap */
NULL, /* bitmap */
NULL, /* bitplane */
1, /* last_pen */
DEFAULT_WIDTH, /* page width */
DEFAULT_HEIGHT, /* page height */
DEFAULT_FILENAME, /* output file */
1, /* page counter */
0, /* cube_size */
NULL, /* temp_rport */
NULL, /* temp_array */
NULL /* pens */
};
/* ILBM device: renders the imagery and saves it to an IFF-ILBM file. */
gx_device_amiga gs_amiga_ilbm_device =
{
sizeof(gx_device_amiga), /* params_size */
&amiga_ilbm_procs, /* procs */
"amiga_ilbm", /* dname */
0, 0, /* width, height */
72.27, 72.27, /* xdpi, ydpi */
no_margins, /* margins */
dci_black_and_white, /* color info */
0, /* is_open */
NULL, /* screen */
NULL, /* window */
0, /* super_width */
0, /* super_height */
NULL, /* super_bitmap */
NULL, /* gadget */
NULL, /* image */
NULL, /* dispatcher */
NULL, /* main */
NULL, /* rport */
NULL, /* printer */
NULL, /* port */
NULL, /* colormap */
NULL, /* bitmap */
NULL, /* bitplane */
1, /* last_pen */
DEFAULT_WIDTH, /* page width */
DEFAULT_HEIGHT, /* page height */
DEFAULT_FILENAME, /* output file */
1, /* page counter */
0, /* cube_size */
NULL, /* temp_rport */
NULL, /* temp_array */
NULL /* pens */
};
/* Dark (black) and light (white) rendering colours; the default device
* determines the actual colours to be used by looking into the screen
* colour lookup table, the other device drivers leave these values
* untouched.
*/
STATIC UBYTE DarkPen = 0,
LightPen = 1;
/* Cheap, but effective ;-) */
#define xdev ((gx_device_amiga *)dev)
/* set_mono_device(gx_device_amiga *dev,int cube_size,LONG *pens):
*
* Reconfigure a device for monochrome output.
*/
VOID
set_mono_device(gx_device_amiga *dev)
{
xdev -> color_info . depth = 1;
xdev -> color_info . num_components = 1;
xdev -> color_info . max_gray = 1;
xdev -> color_info . max_rgb = 0;
xdev -> color_info . dither_gray = 2;
xdev -> color_info . dither_rgb = 0;
xdev -> procs -> copy_color = amiga_copy_color;
xdev -> procs -> map_rgb_color = amiga_map_rgb_color;
xdev -> procs -> map_color_rgb = amiga_map_color_rgb;
xdev -> cube_size = 0;
}
/* set_colour_device(gx_device_amiga *dev,int cube_size,LONG *pens):
*
* Reconfigure a device for colour output.
*/
VOID
set_colour_device(gx_device_amiga *dev,int cube_size,LONG *pens)
{
xdev -> color_info . depth = 8;
xdev -> color_info . num_components = 3;
xdev -> color_info . max_gray = cube_size - 1;
xdev -> color_info . max_rgb = cube_size - 1;
xdev -> color_info . dither_gray = cube_size;
xdev -> color_info . dither_rgb = cube_size;
xdev -> procs -> copy_color = amiga_copy_color8;
/* Any colours to be remapped? */
if(pens)
{
xdev -> procs -> map_rgb_color = amiga_color_map_rgb_color_pen;
xdev -> procs -> map_color_rgb = amiga_color_map_color_rgb_pen;
xdev -> pens = pens;
}
else
{
xdev -> procs -> map_rgb_color = amiga_color_map_rgb_color;
xdev -> procs -> map_color_rgb = amiga_color_map_color_rgb;
}
/* Remember the size of the RGB cube. */
xdev -> cube_size = cube_size;
}
/* set_colour_printer_device(gx_device_amiga *dev,LONG CubeSize):
*
* Configure the printer device for colour output.
*/
VOID
set_colour_printer_device(gx_device_amiga *dev,LONG CubeSize)
{
xdev -> color_info . depth = 16;
xdev -> color_info . num_components = 3;
xdev -> color_info . max_gray = CubeSize - 1;
xdev -> color_info . max_rgb = CubeSize - 1;
xdev -> color_info . dither_gray = CubeSize;
xdev -> color_info . dither_rgb = CubeSize;
xdev -> procs -> fill_rectangle = amiga_fill_rectangle_raw_color;
xdev -> procs -> copy_mono = amiga_copy_mono_raw_color;
xdev -> procs -> copy_color = amiga_copy_color_raw_color16;
xdev -> procs -> draw_line = amiga_draw_line_raw_color;
xdev -> procs -> get_bits = gx_default_get_bits;
xdev -> procs -> map_rgb_color = amiga_color_map_rgb_color;
xdev -> procs -> map_color_rgb = amiga_color_map_color_rgb;
xdev -> cube_size = CubeSize;
}
/* DeleteBitMap(struct BitMap *BitMap,BOOL Private):
*
* Free memory associated with a custom rendering bitmap.
*/
VOID
DeleteBitMap(struct BitMap *BitMap,BOOL Private)
{
if(GfxBase -> LibNode . lib_Version >= 39 && !Private)
FreeBitMap(BitMap);
else
{
LONG i;
for(i = 0 ; i < BitMap -> Depth ; i++)
{
if(BitMap -> Planes[i])
FreeVec(BitMap -> Planes[i]);
}
FreeVec(BitMap);
}
}
/* CreateBitMap(LONG Width,LONG Height,LONG Depth,ULONG Flags,struct BitMap *Friend,BOOL Private):
*
* Create a custom rendering bitmap.
*/
struct BitMap *
CreateBitMap(LONG Width,LONG Height,LONG Depth,ULONG Flags,struct BitMap *Friend,BOOL Private)
{
if(GfxBase -> LibNode . lib_Version >= 39 && !Private)
return(AllocBitMap(Width,Height,Depth,Flags,Friend));
else
{
struct BitMap *BitMap;
LONG Plus;
ULONG MemType;
/* Bitmap structure needs to be padded if more
* than the standard eight bitplanes are to be
* allocated.
*/
if(Depth > 8)
Plus = (Depth - 8) * sizeof(PLANEPTR);
else
Plus = 0;
if(Private)
MemType = MEMF_ANY;
else
MemType = MEMF_CHIP;
if(BitMap = (struct BitMap *)AllocVec(sizeof(struct BitMap) + Plus,MEMF_ANY | MEMF_CLEAR))
{
LONG i,PageSize;
InitBitMap(BitMap,Depth,Width,Height);
PageSize = BitMap -> BytesPerRow * BitMap -> Rows;
for(i = 0 ; i < BitMap -> Depth ; i++)
{
if(!(BitMap -> Planes[i] = (PLANEPTR)AllocVec(PageSize,MemType)))
{
LONG j;
for(j = 0 ; j < i ; j++)
FreeVec(BitMap -> Planes[j]);
FreeVec(BitMap);
return(NULL);
}
}
return(BitMap);
}
}
}
/* DeleteTempRPort(struct RastPort *Temp):
*
* Free memory associated with a temporary raster port.
*/
VOID
DeleteTempRPort(struct RastPort *Temp)
{
DeleteBitMap(Temp -> BitMap,FALSE);
FreeVec(Temp);
}
/* CreateTempRPort(struct RastPort *Source):
*
* Allocate memory for temporary raster port (one line high).
*/
struct RastPort *
CreateTempRPort(struct RastPort *Source)
{
struct RastPort *Temp;
if(Temp = (struct RastPort *)AllocVec(sizeof(struct RastPort),MEMF_ANY))
{
LONG Width,Depth;
CopyMem(Source,Temp,sizeof(struct RastPort));
Temp -> Layer = NULL;
if(GfxBase -> LibNode . lib_Version >= 39)
{
Width = GetBitMapAttr(Source -> BitMap,BMA_WIDTH);
Depth = GetBitMapAttr(Source -> BitMap,BMA_DEPTH);
}
else
{
Width = Source -> BitMap -> BytesPerRow * 8;
Depth = Source -> BitMap -> Depth;
}
if(Temp -> BitMap = CreateBitMap(Width,1,Depth,NULL,Source -> BitMap,FALSE))
return(Temp);
else
FreeVec(Temp);
}
return(NULL);
}
/* Euclid(LONG a,LONG b):
*
* Compute the greatest common divisor of two integers.
*/
LONG
Euclid(LONG a,LONG b)
{
do
{
if(a < b)
{
LONG t;
t = a;
a = b;
b = t;
}
a = a % b;
}
while(a);
return(b);
}
/* PutDump(register BYTE *Destination,register LONG Count):
*
* Store a byte dump.
*/
BYTE *
PutDump(register BYTE *Destination,register LONG Count)
{
register BYTE *Source = Buffer;
*Destination++ = Count - 1;
PackedBytes += Count + 1;
while(Count--)
*Destination++ = *Source++;
return(Destination);
}
/* PutRun(register BYTE *Destination,LONG Count,WORD Char):
*
* Store a byte run.
*/
BYTE *
PutRun(register BYTE *Destination,LONG Count,WORD Char)
{
*Destination++ = -(Count - 1);
*Destination++ = Char;
PackedBytes += 2;
return(Destination);
}
/* PackRow(PLANEPTR *SourcePtr,register BYTE *Destination,LONG RowSize):
*
* Pack a raster line using the CmpByteRun1 algorithm.
*/
LONG
PackRow(PLANEPTR *SourcePtr,register BYTE *Destination,LONG RowSize)
{
register BYTE *Source = *SourcePtr;
WORD Buffered = 1,
RunStart = 0;
BYTE Mode = DUMP,
LastChar,
Char;
PackedBytes = 0;
Buffer[0] = LastChar = Char = *Source++;
RowSize--;
while(RowSize--)
{
Buffer[Buffered++] = Char = *Source++;
if(Mode)
{
if((Char != LastChar) || (Buffered - RunStart > MAXRUN))
{
Destination = PutRun(Destination,Buffered - 1 - RunStart,LastChar);
Buffer[0] = Char;
Buffered = 1;
RunStart = 0;
Mode = DUMP;
}
}
else
{
if(Buffered > MAXDAT)
{
Destination = PutDump(Destination,Buffered - 1);
Buffer[0] = Char;
Buffered = 1;
RunStart = 0;
}
else
{
if(Char == LastChar)
{
if(Buffered - RunStart >= MINRUN)
{
if(RunStart)
Destination = PutDump(Destination,RunStart);
Mode = RUN;
}
else
{
if(!RunStart)
Mode = RUN;
}
}
else
RunStart = Buffered - 1;
}
}
LastChar = Char;
}
if(Mode)
PutRun(Destination,Buffered - RunStart,LastChar);
else
PutDump(Destination,Buffered);
*SourcePtr = Source;
return(PackedBytes);
}
/* PutBODY(struct IFFHandle *Handle,struct BitMap *BitMap):
*
* Store a bitmap in a BODY chunk.
*/
BOOL
PutBODY(struct IFFHandle *Handle,struct BitMap *BitMap)
{
PLANEPTR *Planes;
BYTE *PackBuffer;
BOOL Success = FALSE;
LONG PackedBytes,
i,j;
/* Allocate the bitplane information. */
if(Planes = (PLANEPTR *)AllocVec(BitMap -> Depth * sizeof(PLANEPTR *),MEMF_ANY | MEMF_CLEAR))
{
/* Allocate the compression buffer. */
if(PackBuffer = (BYTE *)AllocVec(BitMap -> BytesPerRow * 2,MEMF_ANY))
{
/* Copy the planes over. */
for(i = 0 ; i < BitMap -> Depth ; i++)
Planes[i] = BitMap -> Planes[i];
if(!PushChunk(Handle,0,ID_BODY,IFFSIZE_UNKNOWN))
{
Success = TRUE;
/* Run down the rows. */
for(i = 0 ; Success && i < BitMap -> Rows ; i++)
{
for(j = 0 ; Success && j < BitMap -> Depth ; j++)
{
/* Pack the data. */
PackedBytes = PackRow(&Planes[j],PackBuffer,BitMap -> BytesPerRow);
/* Write it to disk. */
if(WriteChunkRecords(Handle,PackBuffer,PackedBytes,1) != 1)
Success = FALSE;
}
}
if(PopChunk(Handle))
Success = FALSE;
}
FreeVec(PackBuffer);
}
FreeVec(Planes);
}
return(Success);
}
/* PutANNO(struct IFFHandle *Handle):
*
* Store annotation chunk.
*/
BOOL
PutANNO(struct IFFHandle *Handle)
{
STATIC STRPTR Note = "Rendered by GNU Ghostscript 2.6.0";
if(!PushChunk(Handle,0,ID_ANNO,strlen(Note)))
{
if(WriteChunkRecords(Handle,Note,strlen(Note),1) == 1)
{
if(!PopChunk(Handle))
return(TRUE);
}
}
return(FALSE);
}
/* PutCAMG(struct IFFHandle *Handle):
*
* Store display mode chunk.
*/
BOOL
PutCAMG(struct IFFHandle *Handle)
{
ULONG ViewModes = HIRESLACE_KEY;
if(!PushChunk(Handle,0,ID_CAMG,sizeof(ULONG)))
{
if(WriteChunkRecords(Handle,&ViewModes,sizeof(ULONG),1) == 1)
{
if(!PopChunk(Handle))
return(TRUE);
}
}
return(FALSE);
}
/* PutCMAP(struct IFFHandle *Handle):
*
* Store colour map chunk.
*/
BOOL
PutCMAP(struct IFFHandle *Handle)
{
STATIC UBYTE Colours[2][3] =
{
0x00,0x00,0x00,
0xFF,0xFF,0xFF
};
if(!PushChunk(Handle,0,ID_CMAP,sizeof(Colours)))
{
if(WriteChunkRecords(Handle,Colours,2,3) == 3)
{
if(!PopChunk(Handle))
return(TRUE);
}
}
return(FALSE);
}
/* PutDPI(struct IFFHandle *Handle,UWORD X_DPI,UWORD Y_DPI):
*
* Store DPI chunk.
*/
BOOL
PutDPI(struct IFFHandle *Handle,UWORD X_DPI,UWORD Y_DPI)
{
DPIHeader Header;
Header . dpi_x = X_DPI;
Header . dpi_y = Y_DPI;
if(!PushChunk(Handle,0,ID_DPI,sizeof(Header)))
{
if(WriteChunkRecords(Handle,&Header,sizeof(Header),1) == 1)
{
if(!PopChunk(Handle))
return(TRUE);
}
}
return(FALSE);
}
/* PutBMHD(struct IFFHandle *Handle,LONG Width,LONG Height,UWORD X_DPI,UWORD Y_DPI):
*
* Store BMHD chunk.
*/
BOOL
PutBMHD(struct IFFHandle *Handle,LONG Width,LONG Height,UWORD X_DPI,UWORD Y_DPI)
{
/* Valid parameters? */
if(X_DPI > 0 && Y_DPI > 0 && Width > 0 && Height > 0)
{
BitMapHeader Header;
UWORD gcd;
/* So we can store neat & small
* aspect ration values.
*/
gcd = Euclid(X_DPI,Y_DPI);
Header . w = Width;
Header . h = Height;
Header . pageWidth = Width;
Header . pageHeight = Height;
Header . x = 0;
Header . y = 0;
Header . nPlanes = 1;
Header . masking = 0;
Header . compression = 1;
Header . pad1 = 0;
Header . transparentColor = 0;
Header . xAspect = X_DPI / gcd;
Header . yAspect = Y_DPI / gcd;
if(!PushChunk(Handle,0,ID_BMHD,sizeof(Header)))
{
if(WriteChunkRecords(Handle,&Header,sizeof(Header),1) == 1)
{
if(!PopChunk(Handle))
return(TRUE);
}
}
}
return(FALSE);
}
/* SaveBitMap(STRPTR Name,struct BitMap *BitMap,LONG Width,LONG Height,UWORD X_DPI,UWORD Y_DPI):
*
* Store a bitmap in an IFF-ILBM file.
*/
BOOL
SaveBitMap(STRPTR Name,struct BitMap *BitMap,LONG Width,LONG Height,UWORD X_DPI,UWORD Y_DPI)
{
struct IFFHandle *Handle;
BOOL Success = FALSE;
if(Handle = AllocIFF())
{
if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
{
InitIFFasDOS(Handle);
if(!OpenIFF(Handle,IFFF_WRITE))
{
if(!PushChunk(Handle,ID_ILBM,ID_FORM,IFFSIZE_UNKNOWN))
{
if(PutBMHD(Handle,Width,Height,X_DPI,Y_DPI))
{
if(PutANNO(Handle))
{
if(PutCMAP(Handle))
{
if(PutCAMG(Handle))
{
if(PutDPI(Handle,X_DPI,Y_DPI))
{
if(PutBODY(Handle,BitMap))
Success = TRUE;
}
}
}
}
}
if(PopChunk(Handle))
Success = FALSE;
}
CloseIFF(Handle);
}
Close(Handle -> iff_Stream);
if(!Success)
DeleteFile(Name);
}
FreeIFF(Handle);
}
return(Success);
}
/* GetInches(STRPTR Buffer):
*
* Turn a parameter string into a number representing
* a certain number of inches.
*/
float
GetInches(STRPTR Buffer)
{
STATIC struct { STRPTR Unit; float Factor; } Units[7] =
{
"pt", 1.0, /* Point */
"pc", 12.0, /* Pica */
"in", 72.72, /* Inch */
"cm", 72.72 / 2.54, /* Centimeter */
"mm", 727.2 / 2.54, /* Millimeter */
"dd", 1157.0 / 1238.0, /* Didot point */
"cc", 1157.0 / 103.0 /* Cicero */
};
UBYTE Temp[40];
float Value;
LONG i;
i = 0;
/* Strip the numeric part. */
while((Buffer[i] >= '0' && Buffer[i] <= '9') || Buffer[i] == '.' || Buffer[i] == '+' || Buffer[i] == '-' || Buffer[i] == 'e')
{
Temp[i] = Buffer[i];
i++;
}
/* Provide null-termination. */
Temp[i] = 0;
/* atof() appears to be broken in ixemul.library 39.45. */
sscanf(Temp,"%f",&Value);
Buffer += i;
/* Which measuring unit? */
for(i = 0 ; i < 7 ; i++)
{
/* Return the result in inches. */
if(!Stricmp(Buffer,Units[i] . Unit))
return(Value * Units[i] . Factor / 72.27);
}
/* Return the result in inches. */
return(Value / 72.27);
}
/* DispatchTask():
*
* Asynchronous window message dispatcher.
*/
VOID
DispatchTask()
{
struct Task *me;
gx_device *dev;
/* Set up global data area base register. */
ix_geta4();
/* Who am I? */
me = FindTask(NULL);
/* Wait for wakeup call. */
Wait(SIG_HANDSHAKE);
/* Obtain device pointer. */
dev = me -> tc_UserData;
/* Enable user input. */
if(ModifyIDCMP(xdev -> window,IDCMP_FLAGS))
{
ULONG Mask = 1 << xdev -> window -> UserPort -> mp_SigBit,
Set;
BOOL Done = FALSE;
/* Fill in the dispatcher entry. */
xdev -> dispatcher = me;
/* Ring back. */
Signal((struct Task *)xdev -> main,SIG_HANDSHAKE);
/* Wait for input... */
do
{
Set = Wait(Mask | SIG_KILL);
if(Set & Mask)
DispatchSuperWindow(dev);
if(Set & SIG_KILL)
Done = TRUE;
}
while(!Done);
/* Disable user input. */
ModifyIDCMP(xdev -> window,NULL);
}
/* Disable task switching. */
Forbid();
/* Clear the dispatcher entry. */
xdev -> dispatcher = NULL;
/* Signal the main process that we are done. */
Signal((struct Task *)xdev -> main,SIG_HANDSHAKE);
/* Remove ourselves. */
RemTask(NULL);
}
/* DeleteScrollers(gx_device *dev):
*
* Delete the window border scrollers.
*/
VOID
DeleteScrollers(gx_device *dev)
{
if(xdev -> gadget)
{
if(xdev -> gadget[HORIZONTAL_SCROLLER])
DisposeObject(xdev -> gadget[HORIZONTAL_SCROLLER]);
if(xdev -> gadget[VERTICAL_SCROLLER])
DisposeObject(xdev -> gadget[VERTICAL_SCROLLER]);
if(xdev -> gadget[UP_ARROW])
DisposeObject(xdev -> gadget[UP_ARROW]);
if(xdev -> gadget[DOWN_ARROW])
DisposeObject(xdev -> gadget[DOWN_ARROW]);
if(xdev -> gadget[LEFT_ARROW])
DisposeObject(xdev -> gadget[LEFT_ARROW]);
if(xdev -> gadget[RIGHT_ARROW])
DisposeObject(xdev -> gadget[RIGHT_ARROW]);
FreeVec(xdev -> gadget);
xdev -> gadget = NULL;
}
if(xdev -> image)
{
if(xdev -> image[UP_IMAGE])
DisposeObject(xdev -> image[UP_IMAGE]);
if(xdev -> image[DOWN_IMAGE])
DisposeObject(xdev -> image[DOWN_IMAGE]);
if(xdev -> image[LEFT_IMAGE])
DisposeObject(xdev -> image[LEFT_IMAGE]);
if(xdev -> image[RIGHT_IMAGE])
DisposeObject(xdev -> image[RIGHT_IMAGE]);
FreeVec(xdev -> image);
xdev -> image = NULL;
}
}
/* CreateScrollers(gx_device *dev,struct Screen *Screen):
*
* Create the window border scroller handles.
*/
BOOL
CreateScrollers(gx_device *dev,struct Screen *Screen)
{
BOOL Result = FALSE;
if(xdev -> gadget = (struct Gadget **)AllocVec(sizeof(struct Gadget *) * GADGET_COUNT,MEMF_ANY | MEMF_CLEAR | MEMF_PUBLIC))
{
if(xdev -> image = (struct Image **)AllocVec(sizeof(struct Image *) * IMAGE_COUNT,MEMF_ANY | MEMF_CLEAR | MEMF_PUBLIC))
{
struct DrawInfo *DrawInfo;
if(DrawInfo = GetScreenDrawInfo(Screen))
{
LONG SizeWidth,
SizeHeight;
UWORD SizeType;
if(Screen -> Flags & SCREENHIRES)
{
SizeWidth = 18;
SizeHeight = 10;
SizeType = SYSISIZE_MEDRES;
}
else
{
SizeWidth = 13;
SizeHeight = 11;
SizeType = SYSISIZE_LOWRES;
}
if(xdev -> image[UP_IMAGE] = (struct Image *)NewObject(NULL,"sysiclass",
SYSIA_Size, SizeType,
SYSIA_Which, UPIMAGE,
SYSIA_DrawInfo, DrawInfo,
TAG_DONE))
{
if(xdev -> image[DOWN_IMAGE] = (struct Image *)NewObject(NULL,"sysiclass",
SYSIA_Size, SizeType,
SYSIA_Which, DOWNIMAGE,
SYSIA_DrawInfo, DrawInfo,
TAG_DONE))
{
if(xdev -> image[LEFT_IMAGE] = (struct Image *)NewObject(NULL,"sysiclass",
SYSIA_Size, SizeType,
SYSIA_Which, LEFTIMAGE,
SYSIA_DrawInfo, DrawInfo,
TAG_DONE))
{
if(xdev -> image[RIGHT_IMAGE] = (struct Image *)NewObject(NULL,"sysiclass",
SYSIA_Size, SizeType,
SYSIA_Which, RIGHTIMAGE,
SYSIA_DrawInfo, DrawInfo,
TAG_DONE))
{
if(xdev -> gadget[VERTICAL_SCROLLER] = NewObject(NULL,"propgclass",
GA_ID, VERTICAL_SCROLLER,
GA_Top, Screen -> WBorTop + Screen -> Font -> ta_YSize + 2,
GA_RelHeight, -(Screen -> WBorTop + Screen -> Font -> ta_YSize + 2 + SizeHeight + 1 + 2 * ARROW_HEIGHT),
GA_Width, SizeWidth - 8,
GA_RelRight, -(SizeWidth - 5),
GA_GZZGadget, TRUE,
GA_Immediate, TRUE,
GA_FollowMouse, TRUE,
GA_RelVerify, TRUE,
GA_RightBorder, TRUE,
PGA_Freedom, FREEVERT,
PGA_NewLook, TRUE,
PGA_Borderless, TRUE,
PGA_Visible, 1,
PGA_Total, 1,
TAG_DONE))
{
if(xdev -> gadget[HORIZONTAL_SCROLLER] = NewObject(NULL,"propgclass",
GA_ID, HORIZONTAL_SCROLLER,
GA_Previous, xdev -> gadget[VERTICAL_SCROLLER],
GA_Height, SizeHeight - 4,
GA_RelBottom, -(SizeHeight - 4 + 1),
GA_Left, 4,
GA_RelWidth, -(2 + SizeWidth + 4 + 2 * ARROW_WIDTH),
GA_GZZGadget, TRUE,
GA_Immediate, TRUE,
GA_FollowMouse, TRUE,
GA_RelVerify, TRUE,
GA_BottomBorder,TRUE,
PGA_Freedom, FREEHORIZ,
PGA_NewLook, TRUE,
PGA_Borderless, TRUE,
PGA_Visible, 1,
PGA_Total, 1,
TAG_DONE))
{
STATIC struct TagItem ArrowMappings[] = { GA_ID, GA_ID, TAG_END };
if(xdev -> gadget[UP_ARROW] = NewObject(NULL,"buttongclass",
GA_ID, UP_ARROW,
GA_Previous, xdev -> gadget[HORIZONTAL_SCROLLER],
GA_GZZGadget, TRUE,
GA_Image, xdev -> image[UP_IMAGE],
GA_RelRight, -(SizeWidth - 1),
GA_RelBottom, -(SizeHeight - 1 + 2 * ARROW_HEIGHT),
GA_Height, ARROW_HEIGHT,
GA_Width, SizeWidth,
GA_Immediate, TRUE,
GA_RelVerify, TRUE,
GA_RightBorder, TRUE,
ICA_TARGET, ICTARGET_IDCMP,
ICA_MAP, ArrowMappings,
TAG_DONE))
{
if(xdev -> gadget[DOWN_ARROW] = NewObject(NULL,"buttongclass",
GA_ID, DOWN_ARROW,
GA_Previous, xdev -> gadget[UP_ARROW],
GA_GZZGadget, TRUE,
GA_Image, xdev -> image[DOWN_IMAGE],
GA_RelRight, -(SizeWidth - 1),
GA_RelBottom, -(SizeHeight - 1 + ARROW_HEIGHT),
GA_Height, ARROW_HEIGHT,
GA_Width, SizeWidth,
GA_Immediate, TRUE,
GA_RelVerify, TRUE,
GA_RightBorder, TRUE,
ICA_TARGET, ICTARGET_IDCMP,
ICA_MAP, ArrowMappings,
TAG_DONE))
{
if(xdev -> gadget[LEFT_ARROW] = NewObject(NULL,"buttongclass",
GA_ID, LEFT_ARROW,
GA_Previous, xdev -> gadget[DOWN_ARROW],
GA_GZZGadget, TRUE,
GA_Image, xdev -> image[LEFT_IMAGE],
GA_RelRight, -(SizeWidth - 1 + 2 * ARROW_WIDTH),
GA_RelBottom, -(SizeHeight - 1),
GA_Height, SizeHeight,
GA_Width, ARROW_WIDTH,
GA_Immediate, TRUE,
GA_RelVerify, TRUE,
GA_BottomBorder,TRUE,
ICA_TARGET, ICTARGET_IDCMP,
ICA_MAP, ArrowMappings,
TAG_DONE))
{
if(xdev -> gadget[RIGHT_ARROW] = NewObject(NULL,"buttongclass",
GA_ID, RIGHT_ARROW,
GA_Previous, xdev -> gadget[LEFT_ARROW],
GA_GZZGadget, TRUE,
GA_Image, xdev -> image[RIGHT_IMAGE],
GA_RelRight, -(SizeWidth - 1 + ARROW_WIDTH),
GA_RelBottom, -(SizeHeight - 1),
GA_Height, SizeHeight,
GA_Width, ARROW_WIDTH,
GA_Immediate, TRUE,
GA_RelVerify, TRUE,
GA_BottomBorder,TRUE,
ICA_TARGET, ICTARGET_IDCMP,
ICA_MAP, ArrowMappings,
TAG_DONE))
Result = TRUE;
}
}
}
}
}
}
}
}
}
FreeScreenDrawInfo(Screen,DrawInfo);
}
}
}
return(Result);
}
/* WindowResize(gx_device *dev):
*
* Update the slider sizes and positions after the window
* was resized.
*/
VOID
WindowResize(gx_device *dev)
{
LONG DeltaX,
DeltaY,
Temp;
/* Query the current horizontal slider position. */
if((Temp = LAYERXOFFSET(xdev -> window) + xdev -> window -> GZZWidth) > xdev -> super_width)
DeltaX = xdev -> super_width - Temp;
else
DeltaX = 0;
/* Query the current vertical slider position. */
if((Temp = LAYERYOFFSET(xdev -> window) + xdev -> window -> GZZHeight) > xdev -> super_height)
DeltaY = xdev -> super_height - Temp;
else
DeltaY = 0;
/* Move the currently displayed window area around. */
if(DeltaX || DeltaY)
ScrollLayer(NULL,xdev -> window -> RPort -> Layer,DeltaX,DeltaY);
/* Update the new horizontal slider position and size. */
SetGadgetAttrs(xdev -> gadget[HORIZONTAL_SCROLLER],xdev -> window,NULL,
PGA_Top, LAYERXOFFSET(xdev -> window),
PGA_Visible, xdev -> window -> GZZWidth,
PGA_Total, xdev -> super_width,
TAG_DONE);
/* Update the new vertical slider position and size. */
SetGadgetAttrs(xdev -> gadget[VERTICAL_SCROLLER],xdev -> window,NULL,
PGA_Top, LAYERYOFFSET(xdev -> window),
PGA_Visible, xdev -> window -> GZZHeight,
PGA_Total, xdev -> super_height,
TAG_DONE);
}
/* WindowUpdate(struct Gadget *Gadget,gx_device *dev):
*
* Move the currently visible portion of the
* window according to the current slider
* position.
*/
VOID
WindowUpdate(struct Gadget *Gadget,gx_device *dev)
{
LONG Storage;
switch(Gadget -> GadgetID)
{
case HORIZONTAL_SCROLLER:
if(GetAttr(PGA_Top,Gadget,&Storage))
ScrollLayer(NULL,xdev -> window -> RPort -> Layer,Storage - LAYERXOFFSET(xdev -> window),0);
break;
case VERTICAL_SCROLLER:
if(GetAttr(PGA_Top,Gadget,&Storage))
ScrollLayer(NULL,xdev -> window -> RPort -> Layer,0,Storage - LAYERYOFFSET(xdev -> window));
break;
}
}
/* MoveAround(struct Gadget *Gadget,int How,gx_device *dev):
*
* Move the currently visible window area according to
* user input.
*/
VOID
MoveAround(struct Gadget *Gadget,LONG How,gx_device *dev)
{
LONG Storage;
if(GetAttr(PGA_Top,Gadget,&Storage))
{
LONG Max;
switch(Gadget -> GadgetID)
{
case HORIZONTAL_SCROLLER:
Max = xdev -> super_width - xdev -> window -> GZZWidth;
break;
case VERTICAL_SCROLLER:
Max = xdev -> super_height - xdev -> window -> GZZHeight;
break;
}
switch(How)
{
case MOVE_MIN:
Storage = 0;
break;
case MOVE_MAX:
Storage = Max;
break;
case MOVE_DOWN:
if(Storage > xdev -> super_height / 100)
Storage -= xdev -> super_height / 100;
else
Storage = 0;
break;
case MOVE_FAR_DOWN:
if(Storage > xdev -> super_height / 10)
Storage -= xdev -> super_height / 10;
else
Storage = 0;
break;
case MOVE_FAR_UP:
if(Storage + xdev -> super_width / 10 < Max)
Storage += xdev -> super_width / 10;
else
Storage = Max;
break;
case MOVE_UP:
if(Storage + xdev -> super_width / 100 < Max)
Storage += xdev -> super_width / 100;
else
Storage = Max;
break;
}
switch(Gadget -> GadgetID)
{
case HORIZONTAL_SCROLLER:
if(LAYERXOFFSET(xdev -> window) != Storage)
{
ScrollLayer(NULL,xdev -> window -> RPort -> Layer,Storage - LAYERXOFFSET(xdev -> window),0);
SetGadgetAttrs(Gadget,xdev -> window,NULL,
PGA_Top,Storage,
TAG_DONE);
}
break;
case VERTICAL_SCROLLER:
if(LAYERYOFFSET(xdev -> window) != Storage)
{
ScrollLayer(NULL,xdev -> window -> RPort -> Layer,0,Storage - LAYERYOFFSET(xdev -> window));
SetGadgetAttrs(Gadget,xdev -> window,NULL,
PGA_Top,Storage,
TAG_DONE);
}
break;
}
}
}
/* DispatchSuperWindow(gx_device *dev):
*
* Dispatch user window input.
*/
VOID
DispatchSuperWindow(gx_device *dev)
{
STATIC struct Gadget *CurrentGadget = NULL;
struct IntuiMessage *IntuiMessage;
ULONG MsgClass,
MsgCode,
MsgQualifier;
struct Gadget *MsgGadget;
while(IntuiMessage = (struct IntuiMessage *)GetMsg(xdev -> window -> UserPort))
{
MsgClass = IntuiMessage -> Class;
MsgCode = IntuiMessage -> Code;
MsgQualifier = IntuiMessage -> Qualifier;
MsgGadget = IntuiMessage -> IAddress;
ReplyMsg((struct Message *)IntuiMessage);
switch(MsgClass)
{
case IDCMP_VANILLAKEY:
if(MsgCode == '\033' || MsgCode == '\003')
Signal((struct Task *)xdev -> main,SIG_KILL);
break;
case IDCMP_RAWKEY:
switch(MsgCode)
{
case HELP_CODE:
DisplayBeep(xdev -> window -> WScreen);
break;
case CURSORUP:
if(MsgQualifier & IEQUALIFIER_CONTROL)
MoveAround(xdev -> gadget[VERTICAL_SCROLLER],MOVE_MIN,dev);
else
{
if(MsgQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
MoveAround(xdev -> gadget[VERTICAL_SCROLLER],MOVE_FAR_DOWN,dev);
else
MoveAround(xdev -> gadget[VERTICAL_SCROLLER],MOVE_DOWN,dev);
}
break;
case CURSORLEFT:
if(MsgQualifier & IEQUALIFIER_CONTROL)
MoveAround(xdev -> gadget[HORIZONTAL_SCROLLER],MOVE_MIN,dev);
else
{
if(MsgQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
MoveAround(xdev -> gadget[HORIZONTAL_SCROLLER],MOVE_FAR_DOWN,dev);
else
MoveAround(xdev -> gadget[HORIZONTAL_SCROLLER],MOVE_DOWN,dev);
}
break;
case CURSORRIGHT:
if(MsgQualifier & IEQUALIFIER_CONTROL)
MoveAround(xdev -> gadget[HORIZONTAL_SCROLLER],MOVE_MAX,dev);
else
{
if(MsgQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
MoveAround(xdev -> gadget[HORIZONTAL_SCROLLER],MOVE_FAR_UP,dev);
else
MoveAround(xdev -> gadget[HORIZONTAL_SCROLLER],MOVE_UP,dev);
}
break;
case CURSORDOWN:
if(MsgQualifier & IEQUALIFIER_CONTROL)
MoveAround(xdev -> gadget[VERTICAL_SCROLLER],MOVE_MAX,dev);
else
{
if(MsgQualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
MoveAround(xdev -> gadget[VERTICAL_SCROLLER],MOVE_FAR_UP,dev);
else
MoveAround(xdev -> gadget[VERTICAL_SCROLLER],MOVE_UP,dev);
}
break;
default:
break;
}
break;
case IDCMP_CLOSEWINDOW:
Signal((struct Task *)xdev -> main,SIG_KILL);
break;
case IDCMP_GADGETDOWN:
CurrentGadget = MsgGadget;
WindowUpdate(MsgGadget,dev);
break;
case IDCMP_GADGETUP:
CurrentGadget = NULL;
WindowUpdate(MsgGadget,dev);
break;
case IDCMP_MOUSEMOVE:
if(CurrentGadget)
WindowUpdate(CurrentGadget,dev);
break;
case IDCMP_IDCMPUPDATE:
switch(GetTagData(GA_ID,0,(struct TagItem *)MsgGadget))
{
case UP_ARROW:
MoveAround(xdev -> gadget[VERTICAL_SCROLLER],MOVE_DOWN,dev);
break;
case DOWN_ARROW:
MoveAround(xdev -> gadget[VERTICAL_SCROLLER],MOVE_UP,dev);
break;
case LEFT_ARROW:
MoveAround(xdev -> gadget[HORIZONTAL_SCROLLER],MOVE_DOWN,dev);
break;
case RIGHT_ARROW:
MoveAround(xdev -> gadget[HORIZONTAL_SCROLLER],MOVE_UP,dev);
break;
default:
break;
}
break;
case IDCMP_NEWSIZE:
WindowResize(dev);
break;
default:
break;
}
}
}
/* Simple routine to call the cleanup routine of a device,
* all devices are smart enough to handle shutdown in
* case they have not been opened yet.
*/
STATIC void __inline
close_device(gx_device_amiga *dev)
{
(*xdev -> procs -> close_device)((gx_device *)dev);
}
/* devcleanup():
*
* Clean up all devices, free all resources.
*/
void
devcleanup()
{
close_device(&gs_amiga_device);
close_device(&gs_amiga_low_device);
close_device(&gs_amiga_high_device);
close_device(&gs_amiga_super_device);
close_device(&gs_amiga_a2024_device);
close_device(&gs_amiga_printer_device);
close_device(&gs_amiga_ilbm_device);
}
/* amiga_set_pen(gx_device *dev,gx_color_index color):
*
* Sets the rendering pen and remembers the current
* settings.
*/
STATIC VOID __inline
amiga_set_pen(gx_device *dev,gx_color_index color)
{
if(xdev -> last_pen != color)
SetAPen(xdev -> rport,xdev -> last_pen = color);
}
/* amiga_map_rgb_color(gx_device *dev,gx_color_value red,gx_color_value green,gx_color_value blue):
*
* Map a colour either to the black or the light rendering pen.
*/
gx_color_index
amiga_map_rgb_color(gx_device *dev,gx_color_value red,gx_color_value green,gx_color_value blue)
{
if((red | green | blue) > gx_max_color_value / 2)
return(LightPen);
else
return(DarkPen);
}
/* amiga_map_color_rgb(gx_device *dev,gx_color_index color,gx_color_value rgb[3]):
*
* Map the light/dark rendering pen to RGB values.
*/
int
amiga_map_color_rgb(gx_device *dev,gx_color_index color,gx_color_value rgb[3])
{
int i;
if(color == LightPen)
{
for(i = 0 ; i < 3 ; i++)
rgb[i] = gx_max_color_value;
}
else
{
for(i = 0 ; i < 3 ; i++)
rgb[i] = 0;
}
return(0);
}
/* AllocatePens(struct ViewPort *VPort,LONG CubeSize):
*
* Allocate shareable viewport pens.
*/
LONG *
AllocatePens(struct ViewPort *VPort,LONG CubeSize)
{
if(GfxBase -> LibNode . lib_Version >= 39)
{
LONG Total = CubeSize * CubeSize * CubeSize,*Pens;
if(Pens = (LONG *)AllocVec(sizeof(LONG) * Total,MEMF_ANY))
{
LONG i,r,g,b,max = CubeSize - 1;
for(i = 0 ; i < Total ; i++)
Pens[i] = -1;
i = 0;
for(r = 0 ; r < CubeSize ; r++)
{
for(g = 0 ; g < CubeSize ; g++)
{
for(b = 0 ; b < CubeSize ; b++)
{
if((Pens[i++] = ObtainBestPen(VPort -> ColorMap,SPREAD((255 * r) / max),SPREAD((255 * g) / max),SPREAD((255 * b) / max),
OBP_FailIfBad, TRUE,
OBP_Precision, PRECISION_IMAGE,
TAG_DONE)) == -1)
{
FreeVec(Pens);
return(NULL);
}
}
}
}
return(Pens);
}
}
return(NULL);
}
/* amiga_open_default(gx_device *dev):
*
* Open the default device, i.e. a window on the Workbench screen.
*/
int
amiga_open_default(gx_device *dev)
{
struct Screen *DefaultScreen;
/* Get a lock on the default public screen. */
if(DefaultScreen = LockPubScreen(NULL))
{
struct DisplayInfo DisplayInfo;
ULONG Mode;
/* Get the default public screen display mode. */
Mode = GetVPModeID(&DefaultScreen -> ViewPort);
/* Inquire display mode information. */
if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,Mode))
{
LONG ScreenWidth,
ScreenHeight;
LONG i;
float Width,
Height;
BOOL GotMode = FALSE;
LONG Depth;
if(GfxBase -> LibNode . lib_Version >= 39)
Depth = GetBitMapAttr(DefaultScreen -> RastPort . BitMap,BMA_DEPTH);
else
Depth = DefaultScreen -> RastPort . BitMap -> Depth;
/* Determine screen view dimensions. */
if(DefaultScreen -> ViewPort . ColorMap -> cm_vpe)
{
struct ViewPortExtra *Extra = DefaultScreen -> ViewPort . ColorMap -> cm_vpe;
ScreenWidth = Extra -> DisplayClip . MaxX - Extra -> DisplayClip . MinX + 1;
ScreenHeight = Extra -> DisplayClip . MaxY - Extra -> DisplayClip . MinY + 1;
}
else
{
struct ViewPortExtra *Extra;
if(Extra = (struct ViewPortExtra *)GfxLookUp(&DefaultScreen -> ViewPort))
{
ScreenWidth = Extra -> DisplayClip . MaxX - Extra -> DisplayClip . MinX + 1;
ScreenHeight = Extra -> DisplayClip . MaxY - Extra -> DisplayClip . MinY + 1;
}
else
{
ScreenWidth = DefaultScreen -> Width;
ScreenHeight = DefaultScreen -> Height;
}
}
/* Determine the screen resolution. */
for(i = 0 ; i < 4 ; i++)
{
if((Mode & mode_dpi_table[i] . mode) == mode_dpi_table[i] . mode)
{
xdev -> x_pixels_per_inch = mode_dpi_table[i] . dpi;
xdev -> y_pixels_per_inch = (mode_dpi_table[i] . dpi * (float)DisplayInfo . Resolution . x) / (float)DisplayInfo . Resolution . y;
GotMode = TRUE;
break;
}
}
/* Use the best guess, we will take the standard
* low resolution x-dpi value and scale it by
* the pixel speed.
*/
if(!GotMode && DisplayInfo . PixelSpeed)
{
xdev -> x_pixels_per_inch = (35.0 * 140.0) / (float)DisplayInfo . PixelSpeed;
xdev -> y_pixels_per_inch = (xdev -> x_pixels_per_inch * (float)DisplayInfo . Resolution . x) / (float)DisplayInfo . Resolution . y;
}
if(xdev -> width > 0 && xdev -> height > 0)
{
xdev -> super_width = xdev -> width;
xdev -> super_height = xdev -> height;
}
else
{
if(xdev -> page_width > 0.0)
xdev -> super_width = (LONG)(xdev -> page_width * xdev -> x_pixels_per_inch);
else
xdev -> super_width = 640;
if(xdev -> page_height > 0.0)
xdev -> super_height = (LONG)(xdev -> page_height * xdev -> y_pixels_per_inch);
else
xdev -> super_height = 512;
}
/* Allocate a bitmap ready to be used for
* rendering.
*/
if(xdev -> super_bitmap = CreateBitMap(xdev -> super_width,xdev -> super_height,Depth,BMF_DISPLAYABLE,DefaultScreen -> RastPort . BitMap,FALSE))
{
/* Clear the bitplanes. */
BltBitMap(xdev -> super_bitmap,0,0,xdev -> super_bitmap,0,0,xdev -> super_width,xdev -> super_height,0x00,(1 << xdev -> super_bitmap -> Depth) - 1,NULL);
/* Create the scroller handles. */
if(CreateScrollers(dev,DefaultScreen))
{
struct IBox ZoomBox;
/* Set up the window alternate
* position.
*/
ZoomBox . Left = 0;
ZoomBox . Top = DefaultScreen -> BarHeight + 1;
ZoomBox . Width = ScreenWidth;
ZoomBox . Height = ScreenHeight - ZoomBox . Top;
/* Eventually, open the display window. */
if(xdev -> window = OpenWindowTags(NULL,
WA_InnerWidth, MIN(DefaultScreen -> Width / 2,xdev -> super_width),
WA_InnerHeight, MIN(DefaultScreen -> Height / 2,xdev -> super_height),
WA_CloseGadget, TRUE,
WA_DepthGadget, TRUE,
WA_SizeGadget, TRUE,
WA_SizeBRight, TRUE,
WA_SizeBBottom, TRUE,
WA_Zoom, &ZoomBox,
WA_DragBar, TRUE,
WA_NoCareRefresh, TRUE,
WA_GimmeZeroZero, TRUE,
WA_RMBTrap, TRUE,
WA_SuperBitMap, xdev -> super_bitmap,
WA_Gadgets, xdev -> gadget[VERTICAL_SCROLLER],
WA_CustomScreen, DefaultScreen,
WA_Title, "Ghostscript Amiga output window",
TAG_DONE))
{
if(xdev -> temp_rport = CreateTempRPort(xdev -> window -> RPort))
{
if(xdev -> temp_array = (UBYTE *)AllocVec(xdev -> window -> WScreen -> Width,MEMF_ANY))
{
struct Task *Task;
/* Bring the window dispatcher task
* to life...
*/
if(Task = (struct Task *)CreateTask("Ghostscript window dispatcher",5,DispatchTask,8192))
{
const sigset_t trapped = sigmask(SIGINT);
/* Cheap... */
Task -> tc_UserData = dev;
/* Who's calling? */
xdev -> main = (struct Process *)FindTask(NULL);
/* Don't let anybody interrupt us! */
sigprocmask(SIG_BLOCK,&trapped,NULL);
Forbid();
/* Wake it up. */
Signal(Task,SIG_HANDSHAKE);
/* Clear the handshake bit. */
SetSignal(0,SIG_HANDSHAKE);
/* Wait for the report. */
Wait(SIG_HANDSHAKE);
Permit();
/* Get the result. */
Task = xdev -> dispatcher;
/* Unblock signals. */
sigprocmask(SIG_UNBLOCK,&trapped,NULL);
}
/* Did we succeed in creating
* the dispatcher task?
*/
if(Task)
{
UWORD MaxValue = 0,
MinValue = 15000,
Value,
R,G,B;
/* Set the window limits. */
WindowLimits(xdev -> window,xdev -> window -> BorderLeft + MINIMUM_WIDTH + xdev -> window -> BorderRight,xdev -> window -> BorderTop + MINIMUM_HEIGHT + xdev -> window -> BorderBottom,xdev -> window -> BorderLeft + xdev -> super_width + xdev -> window -> BorderRight,xdev -> window -> BorderTop + xdev -> super_height + xdev -> window -> BorderBottom);
/* Update the sliders. */
WindowResize(dev);
/* Look for the darkest and the lightest screen colours. */
for(i = 0 ; i < MIN(xdev -> window -> WScreen -> ViewPort . ColorMap -> Count,(1 << Depth)) ; i++)
{
Value = GetRGB4(xdev -> window -> WScreen -> ViewPort . ColorMap,i);
R = (Value >> 8) & 0xF;
G = (Value >> 4) & 0xF;
B = Value & 0xF;
/* Luminance conversion included */
Value = R * 299 + G * 588 + B * 113;
if(Value > MaxValue)
{
MaxValue = Value;
LightPen = i;
}
if(Value < MinValue)
{
MinValue = Value;
DarkPen = i;
}
}
/* Fill in the rest. */
xdev -> width = xdev -> super_width;
xdev -> height = xdev -> super_height;
xdev -> rport = xdev -> window -> RPort;
/* Does the display support
* at least eight colours?
*/
if(Depth >= 3)
{
LONG cube_size,max;
/* Set up a fitting colour cube. */
for(cube_size = 6 ; cube_size >= 2 ; cube_size--)
{
if((max = cube_size * cube_size * cube_size) <= 1 << Depth)
break;
}
/* Got enough colours? */
if(cube_size != 1)
{
LONG *Pens;
/* Try to grab the cube colours,
* making a colour display.
*/
if(Pens = AllocatePens(&xdev -> window -> WScreen -> ViewPort,cube_size))
set_colour_device((gx_device_amiga *)dev,cube_size,Pens);
}
}
SetBPen(xdev -> rport,0);
SetDrMd(xdev -> rport,JAM2);
amiga_set_pen(dev,DarkPen);
UnlockPubScreen(NULL,DefaultScreen);
return(0);
}
else
perror("Ghostscript: failed to create dispatcher task");
}
else
perror("Ghostscript: failed to create temporary line buffer.");
}
else
perror("Ghostscript: failed to create temporary raster port");
}
else
perror("Ghostscript: failed to open window");
}
else
perror("Ghostscript: failed to allocate scrollers");
}
else
perror("Ghostscript: failed to allocate bitmap");
}
else
perror("Ghostscript: failed to get display mode information");
UnlockPubScreen(NULL,DefaultScreen);
}
else
perror("Ghostscript: failed to lock default public screen");
return(-1);
}
/* amiga_open_low(gx_device *dev):
*
* Open the low resolution device.
*/
int
amiga_open_low(gx_device *dev)
{
return(amiga_open(dev,LORES_KEY));
}
/* amiga_open_high(gx_device *dev):
*
* Open the high resolution device.
*/
int
amiga_open_high(gx_device *dev)
{
return(amiga_open(dev,HIRESLACE_KEY));
}
/* amiga_open_super(gx_device *dev):
*
* Open the super high resolution device.
*/
int
amiga_open_super(gx_device *dev)
{
/* Fall back to the default if not available. */
if(ModeNotAvailable(SUPERLACE_KEY))
return(amiga_open_high(dev));
else
return(amiga_open(dev,SUPERLACE_KEY));
}
/* amiga_open_a2024(gx_device *dev):
*
* Open the A2024 device.
*/
int
amiga_open_a2024(gx_device *dev)
{
/* Fall back to the default if not available. */
if(ModeNotAvailable(A2024TENHERTZ_KEY))
return(amiga_open_super(dev));
else
return(amiga_open(dev,A2024TENHERTZ_KEY));
/* if(ModeNotAvailable(0xF1004))*/
/* return(amiga_open_high(dev));*/
/* else*/
/* return(amiga_open(dev,0xF1004));*/
}
/* amiga_open_printer(gx_device *dev):
*
* Open the printer device.
*/
int
amiga_open_printer(gx_device *dev)
{
if(xdev -> port = CreateMsgPort())
{
if(xdev -> printer = (struct IODRPReq *)CreateIORequest(xdev -> port,sizeof(struct IODRPReq)))
{
if(!OpenDevice("printer.device",0,(struct IORequest *)xdev -> printer,0))
{
if(xdev -> rport = (struct RastPort *)AllocVec(sizeof(struct RastPort),MEMF_ANY))
{
const sigset_t trapped = sigmask(SIGINT);
struct BitMap DummyBitMap;
UWORD DummyLine[12];
InitRastPort(xdev -> rport);
/* Cook up a dummy bitmap to keep
* `smart' drivers from complaining.
*/
InitBitMap(&DummyBitMap,12,16,1);
DummyBitMap . Planes[0] = (PLANEPTR)&DummyLine;
xdev -> rport -> BitMap = &DummyBitMap;
/* Query page size requirements. */
xdev -> printer -> io_Command = PRD_DUMPRPORT;
xdev -> printer -> io_RastPort = xdev -> rport;
xdev -> printer -> io_ColorMap = xdev -> colormap;
xdev -> printer -> io_SrcWidth = 16;
xdev -> printer -> io_SrcHeight = 1;
xdev -> printer -> io_DestCols = 0;
xdev -> printer -> io_DestRows = 0;
xdev -> printer -> io_Special |= SPECIAL_NOPRINT;
/* Don't let them stop us now! */
sigprocmask(SIG_BLOCK,&trapped,NULL);
/* Ask for it... */
if(!DoIO((struct IORequest *)xdev -> printer))
{
struct PrinterExtendedData *PED;
struct PrinterData *PD;
LONG Depth,
NumColours,
CubeSize;
/* Unblock ^C signal. */
sigprocmask(SIG_UNBLOCK,&trapped,NULL);
/* Get the printer internal data. */
PD = (struct PrinterData *)xdev -> printer -> io_Device;
PED = &PD -> pd_SegmentData -> ps_PED;
/* Set up the default colour values. */
if(PD -> pd_Preferences . PrintShade == SHADE_BW)
{
Depth = 1;
NumColours = 2;
CubeSize = 0;
}
else
{
Depth = 12;
NumColours = 4096;
CubeSize = 16;
}
/* Get the page size */
if(xdev -> width > 0 && xdev -> height > 0)
{
if(PED -> ped_MaxXDots < xdev -> width)
xdev -> width = PED -> ped_MaxXDots;
if(PED -> ped_MaxYDots < xdev -> height)
xdev -> height = PED -> ped_MaxYDots;
}
else
{
xdev -> width = PED -> ped_MaxXDots;
xdev -> height = PED -> ped_MaxYDots;
}
/* Get the DPI values */
xdev -> x_pixels_per_inch = (float)PED -> ped_XDotsInch;
xdev -> y_pixels_per_inch = (float)PED -> ped_YDotsInch;
/* Try to allocate a suitable bitmap.
* If an allocation fails, rescale the
* colour cube and bitmap depth and
* retry. Minimum are eight colours.
*/
do
{
/* Try to allocate the raster... */
if(!(xdev -> bitmap = CreateBitMap(xdev -> width,xdev -> height,Depth,NULL,NULL,TRUE)))
{
/* Any chance to rescale the cube? */
if(Depth < 2)
break;
else
{
/* One plane less... */
Depth--;
/* Rescale the cube. */
while(CubeSize >= 2)
{
if((NumColours = CubeSize * CubeSize * CubeSize) <= (1 << Depth))
break;
else
CubeSize--;
}
/* Less than eight colours? */
if(CubeSize < 2)
break;
}
}
}
while(!xdev -> bitmap);
/* Got the bitmap? */
if(xdev -> bitmap)
{
/* Allocate a suitable colour map. */
if(xdev -> colormap = GetColorMap(NumColours))
{
/* Black & white only? */
if(NumColours == 2)
{
SetRGB4CM(xdev -> colormap,0,0x0,0x0,0x0);
SetRGB4CM(xdev -> colormap,1,0xF,0xF,0xF);
}
else
{
LONG i = 0,r,g,b,max = CubeSize - 1;
/* Fill in the colour cube. */
for(r = 0 ; r < CubeSize ; r++)
{
for(g = 0 ; g < CubeSize ; g++)
{
for(b = 0 ; b < CubeSize ; b++)
SetRGB4CM(xdev -> colormap,i++,(15 * r) / max,(15 * g) / max,(15 * b) / max);
}
}
set_colour_printer_device((gx_device_amiga *)dev,CubeSize);
}
xdev -> rport -> BitMap = xdev -> bitmap;
return(0);
}
else
perror("Ghostscript: failed to allocate colour map");
}
else
{
char buffer[256];
sprintf(buffer,"Ghostscript: failed to allocate raster (wanted %ld, largest %ld)",(xdev -> width + 15) / 8 * xdev -> height * Depth,AvailMem(MEMF_ANY | MEMF_LARGEST));
perror(buffer);
}
}
else
{
char buffer[256];
sigprocmask(SIG_UNBLOCK,&trapped,NULL);
sprintf(buffer,"Ghostscript: failed to query printer page size (error code #%ld)",xdev -> printer -> io_Error);
perror(buffer);
}
}
else
perror("Ghostscript: failed to allocate raster port");
}
else
{
char buffer[256];
sprintf(buffer,"Ghostscript: failed to open printer.device (error code #%ld)",xdev -> printer -> io_Error);
perror(buffer);
}
}
else
perror("Ghostscript: failed to allocate device driver");
}
else
perror("Ghostscript: failed to create io port");
return(-1);
}
/* amiga_output_page_printer(gx_device *dev,int,int):
*
* Send a bitmap to the printer.
*/
int
amiga_output_page_printer(gx_device *dev,int num_copies,int flush)
{
const sigset_t trapped = sigmask(SIGINT);
int result,i;
xdev -> printer -> io_Command = PRD_DUMPRPORT;
xdev -> printer -> io_SrcWidth = xdev -> width;
xdev -> printer -> io_SrcHeight = xdev -> height;
xdev -> printer -> io_DestCols = xdev -> width;
xdev -> printer -> io_DestRows = xdev -> height;
xdev -> printer -> io_Special &= ~SPECIAL_NOPRINT;
/* We cannot possibly allow being interrupted in the middle
* of a raster dump!
*/
sigprocmask(SIG_BLOCK,&trapped,NULL);
for(i = 0 ; i < num_copies ; i++)
{
if(DoIO((struct IORequest *)xdev -> printer))
{
char buffer[256];
sprintf(buffer,"Ghostscript: failed to print raster (error code #%ld)",xdev -> printer -> io_Error);
perror(buffer);
result = -1;
break;
}
else
result = 0;
}
sigprocmask(SIG_UNBLOCK,&trapped,NULL);
return(result);
}
/* amiga_close_printer(gx_device *dev):
*
* Close the printer driver.
*/
int
amiga_close_printer(gx_device *dev)
{
if(xdev -> bitmap)
{
DeleteBitMap(xdev -> bitmap,TRUE);
xdev -> bitmap = NULL;
}
if(xdev -> rport)
{
FreeVec(xdev -> rport);
xdev -> rport = NULL;
}
if(xdev -> colormap)
{
FreeColorMap(xdev -> colormap);
xdev -> colormap = NULL;
}
if(xdev -> printer)
{
if(xdev -> printer -> io_Device)
CloseDevice((struct IORequest *)xdev -> printer);
DeleteIORequest(xdev -> printer);
xdev -> printer = NULL;
}
if(xdev -> port)
{
DeleteMsgPort(xdev -> port);
xdev -> port = NULL;
}
xdev -> width = xdev -> height = 0;
/* xdev -> x_pixels_per_inch = x_pixels_per_inch = 72.72;*/
return(0);
}
/* amiga_get_bits(gx_device *dev,int y,byte *str,byte **actual_data):
*
* Read the raster bits into a buffer.
*/
int
amiga_get_bits(gx_device *dev,int y,byte *str,byte **actual_data)
{
if(y < 0 || y > xdev -> height)
return(-1);
else
{
if(actual_data)
*actual_data = (byte *)(xdev -> bitmap -> Planes[0] + xdev -> bitmap -> BytesPerRow * y);
else
memcpy(str,xdev -> bitmap -> Planes[0] + xdev -> bitmap -> BytesPerRow * y,xdev -> bitmap -> BytesPerRow);
return(0);
}
}
/* amiga_open(gx_device *dev,ULONG Mode):
*
* Open a custom screen.
*/
int
amiga_open(gx_device *dev,ULONG Mode)
{
struct DisplayInfo DisplayInfo;
struct DimensionInfo DimensionInfo;
/* Get the display dimensions. */
if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,Mode) && GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,Mode))
{
/* Two shades only, black & white */
STATIC struct ColorSpec Colours[] =
{
0, 0x0000, 0x0000, 0x0000,
1, 0xFFFF, 0xFFFF, 0xFFFF,
-1
};
float Width,
Height;
LONG i,cube_size,max;
LONG ScreenWidth,
ScreenHeight,
ScreenDepth;
BOOL GotMode = FALSE;
/* Start up with a maximum depth display. */
ScreenDepth = DimensionInfo . MaxDepth;
/* Check to see whether we will be able to
* build a colour display or not.
*/
for(cube_size = 6 ; cube_size >= 2 ; cube_size--)
{
if((max = cube_size * cube_size * cube_size) <= 1 << ScreenDepth)
break;
}
/* Got enough colours? */
if(cube_size != 1)
set_colour_device((gx_device_amiga *)dev,cube_size,NULL);
else
{
ScreenDepth = 1;
set_mono_device((gx_device_amiga *)dev);
}
if(xdev -> width > 0 && xdev -> height > 0)
{
Width = xdev -> width;
Height = xdev -> height;
}
else
{
if(xdev -> page_width > 0.0)
Width = xdev -> page_width;
else
Width = 0.0;
if(xdev -> page_height > 0.0)
Height = xdev -> page_height;
else
Height = 0.0;
}
/* Determine screen resolution */
for(i = 0 ; i < 4 ; i++)
{
if((Mode & mode_dpi_table[i] . mode) == mode_dpi_table[i] . mode)
{
xdev -> x_pixels_per_inch = mode_dpi_table[i] . dpi;
xdev -> y_pixels_per_inch = (mode_dpi_table[i] . dpi * (float)DisplayInfo . Resolution . x) / (float)DisplayInfo . Resolution . y;
GotMode = TRUE;
break;
}
}
/* Use the best guess, we will take the standard
* low resolution x-dpi value and scale it by
* the pixel speed.
*/
if(!GotMode && DisplayInfo . PixelSpeed)
{
xdev -> x_pixels_per_inch = (35.0 * 140.0) / (float)DisplayInfo . PixelSpeed;
xdev -> y_pixels_per_inch = (xdev -> x_pixels_per_inch * (float)DisplayInfo . Resolution . x) / (float)DisplayInfo . Resolution . y;
}
if(Width > 0.0)
ScreenWidth = (LONG)(Width * xdev -> x_pixels_per_inch);
else
ScreenWidth = 0;
if(Height > 0.0)
ScreenHeight = (LONG)(Height * xdev -> y_pixels_per_inch);
else
ScreenHeight = 0;
if(ScreenWidth < DimensionInfo . MinRasterWidth || ScreenWidth > DimensionInfo . MaxRasterWidth)
ScreenWidth = 0;
if(ScreenHeight < DimensionInfo . MinRasterHeight || ScreenHeight > DimensionInfo . MaxRasterHeight)
ScreenHeight = 0;
/* Try to open a custom screen; if this fails, try to
* rescale the colour cube and retry.
*/
do
{
if(!(xdev -> screen = OpenScreenTags(NULL,
SA_Depth, ScreenDepth,
SA_Overscan, OSCAN_TEXT,
SA_Quiet, TRUE,
SA_Behind, TRUE,
SA_DisplayID, Mode,
SA_Colors, Colours,
SA_AutoScroll, TRUE,
SA_ShowTitle, FALSE,
ScreenWidth > 0 ? SA_Width : TAG_IGNORE, ScreenWidth,
ScreenHeight > 0 ? SA_Height : TAG_IGNORE, ScreenHeight,
TAG_DONE)))
{
if(ScreenDepth < 2)
break;
else
{
ScreenDepth--;
/* Check to see whether we will be able to
* build a colour display or not.
*/
while(cube_size >= 2)
{
if((max = cube_size * cube_size * cube_size) <= 1 << ScreenDepth)
break;
else
cube_size--;
}
/* Got enough colours? */
if(cube_size == 1 || ScreenDepth == 1)
{
/* Obviously not. */
ScreenDepth = 1;
set_mono_device((gx_device_amiga *)dev);
}
}
}
}
while(!xdev -> screen);
/* Did we succeed in opening the screen? */
if(xdev -> screen)
{
if(xdev -> window = OpenWindowTags(NULL,
WA_Left, 0,
WA_Top, 0,
WA_Width, xdev -> screen -> Width,
WA_Height, xdev -> screen -> Height,
WA_Backdrop, TRUE,
WA_RMBTrap, TRUE,
WA_Borderless, TRUE,
WA_CustomScreen,xdev -> screen,
TAG_DONE))
{
xdev -> rport = xdev -> window -> RPort;
xdev -> width = xdev -> screen -> Width;
xdev -> height = xdev -> screen -> Height;
}
else
{
xdev -> rport = &xdev -> screen -> RastPort;
xdev -> width = xdev -> screen -> Width;
xdev -> height = xdev -> screen -> Height;
}
/* Establish defaults. */
DarkPen = 0;
LightPen = 1;
SetBPen(xdev -> rport,0);
SetDrMd(xdev -> rport,JAM2);
/* Create the temporary drawing area. */
if(xdev -> temp_rport = CreateTempRPort(xdev -> rport))
{
if(xdev -> temp_array = (UBYTE *)AllocVec(xdev -> screen -> Width,MEMF_ANY))
{
/* Colour output enabled? */
if(xdev -> cube_size > 0)
{
LONG r,g,b,max = xdev -> cube_size - 1;
i = 0;
/* Build a suitable colour map. */
if(GfxBase -> LibNode . lib_Version >= 39)
{
for(r = 0 ; r < xdev -> cube_size ; r++)
{
for(g = 0 ; g < xdev -> cube_size ; g++)
{
for(b = 0 ; b < xdev -> cube_size ; b++)
SetRGB32(&xdev -> screen -> ViewPort,i++,SPREAD((255 * r) / max),SPREAD((255 * g) / max),SPREAD((255 * b) / max));
}
}
}
else
{
for(r = 0 ; r < xdev -> cube_size ; r++)
{
for(g = 0 ; g < xdev -> cube_size ; g++)
{
for(b = 0 ; b < xdev -> cube_size ; b++)
SetRGB4(&xdev -> screen -> ViewPort,i++,(15 * r) / max,(15 * g) / max,(15 * b) / max);
}
}
}
}
}
else
{
perror("Ghostscript: failed to allocate temporary line");
return(-1);
}
}
else
{
perror("Ghostscript: failed to allocate temporary raster");
return(-1);
}
amiga_set_pen(dev,DarkPen);
return(0);
}
else
perror("Ghostscript: failed to open screen");
}
else
perror("Ghostscript: failed to get display mode information");
return(-1);
}
/* amiga_output_page(gx_device *dev,int,int):
*
* Page is not `buffered', just bring screen/window
* to the front.
*/
int
amiga_output_page(gx_device *dev,int num_copies,int flush)
{
if(xdev -> screen)
ScreenToFront(xdev -> screen);
else
{
if(xdev -> window)
WindowToFront(xdev -> window);
}
return(0);
}
/* amiga_close(gx_device *dev):
*
* Close the screen and free associated resources.
*/
int
amiga_close(gx_device *dev)
{
if(xdev -> dispatcher)
{
const sigset_t trapped = sigmask(SIGINT);
sigprocmask(SIG_BLOCK,&trapped,NULL);
Forbid();
Signal(xdev -> dispatcher,SIG_KILL);
SetSignal(0,SIG_HANDSHAKE);
Wait(SIG_HANDSHAKE);
Permit();
sigprocmask(SIG_UNBLOCK,&trapped,NULL);
}
if(xdev -> temp_array)
{
FreeVec(xdev -> temp_array);
xdev -> temp_array = NULL;
}
if(xdev -> pens)
{
LONG i;
for(i = 0 ; i < xdev -> cube_size * xdev -> cube_size * xdev -> cube_size ; i++)
{
if(xdev -> pens[i] != -1)
ReleasePen(xdev -> window -> WScreen -> ViewPort . ColorMap,xdev -> pens[i]);
}
FreeVec(xdev -> pens);
xdev -> pens = NULL;
}
if(xdev -> temp_rport)
{
DeleteTempRPort(xdev -> temp_rport);
xdev -> temp_rport = NULL;
}
if(xdev -> window)
{
CloseWindow(xdev -> window);
xdev -> window = NULL;
}
DeleteScrollers(dev);
if(xdev -> super_bitmap)
{
DeleteBitMap(xdev -> super_bitmap,FALSE);
xdev -> super_bitmap = NULL;
}
if(xdev -> screen)
{
CloseScreen(xdev -> screen);
xdev -> screen = NULL;
}
xdev -> width = xdev -> height = 0;
/* xdev -> x_pixels_per_inch = x_pixels_per_inch = 72.72;*/
return(0);
}
/* amiga_fill_rectangle(gx_device *dev,int x,int y,int w,int h,gx_color_index color):
*
* Fill a rectangle with a given colour. This one is simple as it can
* be done with the Amiga graphics primitives.
*/
int
amiga_fill_rectangle(gx_device *dev,int x,int y,int w,int h,gx_color_index color)
{
if(x < 0 || x > xdev -> width - w || y < 0 || y > xdev -> height - h)
return(-1);
else
{
if(w > 0 && h > 0 && color != gx_no_color_index)
{
amiga_set_pen(dev,color);
RectFill(xdev -> rport,x,y,x + w - 1,y + h - 1);
}
return(0);
}
}
/* amiga_copy_mono():
*
* Copy a monochrome image. This operation requires a bit of work as
* we cannot simply blit the image into the bitmap.
*/
int
amiga_copy_mono(gx_device *dev,const UBYTE *base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)
{
if(y < 0 || x < 0 || w < 0 || h < 0)
return(-1);
else
{
if(w > 0 && h > 0)
{
LONG i,j;
if(zero == gx_no_color_index)
{
if(one != gx_no_color_index)
{
do
{
ReadPixelLine8(xdev -> rport,x,y,w,xdev -> temp_array,xdev -> temp_rport);
for(i = sourcex, j = 0 ; i < sourcex + w ; i++, j++)
{
if(base[i >> 3] & shift[i & 7])
xdev -> temp_array[j] = one;
}
WritePixelLine8(xdev -> rport,x,y,w,xdev -> temp_array,xdev -> temp_rport);
base += raster;
y++;
}
while(--h);
}
}
else
{
if(one == gx_no_color_index)
{
do
{
ReadPixelLine8(xdev -> rport,x,y,w,xdev -> temp_array,xdev -> temp_rport);
for(i = sourcex, j = 0 ; i < w + sourcex ; i++, j++)
{
if(!(base[i >> 3] & shift[i & 7]))
xdev -> temp_array[j] = zero;
}
WritePixelLine8(xdev -> rport,x,y,w,xdev -> temp_array,xdev -> temp_rport);
base += raster;
y++;
}
while(--h);
}
else
{
do
{
for(i = sourcex, j = 0 ; i < w + sourcex ; i++, j++)
{
if(base[i >> 3] & shift[i & 7])
xdev -> temp_array[j] = one;
else
xdev -> temp_array[j] = zero;
}
WritePixelLine8(xdev -> rport,x,y,w,xdev -> temp_array,xdev -> temp_rport);
base += raster;
y++;
}
while(--h);
}
}
}
return(0);
}
}
/* amiga_copy_color():
*
* Copy a color image (oh well...). This is just the same as the
* copy_mono() routine.
*/
int
amiga_copy_color(gx_device *dev,const UBYTE *base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h)
{
if(y < 0 || x < 0 || w < 0 || h < 0)
return(-1);
else
{
if(w > 0 && h > 0)
{
LONG i,j;
do
{
for(i = sourcex, j = 0 ; i < w + sourcex ; i++, j++)
{
if(base[i >> 3] & shift[i & 7])
xdev -> temp_array[j] = DarkPen;
else
xdev -> temp_array[j] = LightPen;
}
WritePixelLine8(xdev -> rport,x,y,w,xdev -> temp_array,xdev -> temp_rport);
base += raster;
y++;
}
while(--h);
}
return(0);
}
}
/* amiga_draw_line(gx_device *dev,int x0,int y0,int x1,int y1,gx_color_index color):
*
* Draw a line between two points. This one is easy as it can be done
* with the Amiga graphics primitives, the only glitch is having to reset
* the last dot to its original colour.
*/
int
amiga_draw_line(gx_device *dev,int x0,int y0,int x1,int y1,gx_color_index color)
{
if(color != gx_no_color_index && (x0 != x1 || y0 != y1))
{
LONG pen;
pen = ReadPixel(xdev -> rport,x1,y1);
amiga_set_pen(dev,color);
Move(xdev -> rport,x0,y0);
Draw(xdev -> rport,x1,y1);
if(pen == color)
{
amiga_set_pen(dev,pen);
WritePixel(xdev -> rport,x1,y1);
}
}
return(0);
}
/* amiga_copy_mono_raw():
*
* Copy a monochrome image to a bitmap. Just watch the
* astounding number of case switches.
*/
int
amiga_copy_mono_raw(gx_device *dev,const UBYTE *base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)
{
if(y < 0 || x < 0 || w < 0 || h < 0)
return(-1);
else
{
if(w > 0 && h > 0)
{
LONG i,j,modulo = xdev -> rport -> BitMap -> BytesPerRow;
UBYTE *line;
w += sourcex;
line = xdev -> rport -> BitMap -> Planes[0] + y * xdev -> rport -> BitMap -> BytesPerRow;
if(zero == gx_no_color_index)
{
if(one != gx_no_color_index)
{
if(one)
{
do
{
for(i = sourcex, j = x ; i < w ; i++, j++)
{
if(base[i >> 3] & shift[i & 7])
line[j >> 3] |= shift[j & 7];
}
base += raster;
line += modulo;
}
while(--h);
}
else
{
do
{
for(i = sourcex, j = x ; i < w ; i++, j++)
{
if(base[i >> 3] & shift[i & 7])
line[j >> 3] &= masks[j & 7];
}
base += raster;
line += modulo;
}
while(--h);
}
}
}
else
{
if(one == gx_no_color_index)
{
if(zero)
{
do
{
for(i = sourcex, j = x ; i < w ; i++, j++)
{
if(!(base[i >> 3] & shift[i & 7]))
line[j >> 3] |= shift[j & 7];
}
base += raster;
line += modulo;
}
while(--h);
}
else
{
do
{
for(i = sourcex, j = x ; i < w ; i++, j++)
{
if(!(base[i >> 3] & shift[i & 7]))
line[j >> 3] &= masks[j & 7];
}
base += raster;
line += modulo;
}
while(--h);
}
}
else
{
if(one)
{
do
{
for(i = sourcex, j = x ; i < w ; i++, j++)
{
if(base[i >> 3] & shift[i & 7])
line[j >> 3] |= shift[j & 7];
else
line[j >> 3] &= masks[j & 7];
}
base += raster;
line += modulo;
}
while(--h);
}
else
{
do
{
for(i = sourcex, j = x ; i < w ; i++, j++)
{
if(base[i >> 3] & shift[i & 7])
line[j >> 3] &= masks[j & 7];
else
line[j >> 3] |= shift[j & 7];
}
base += raster;
line += modulo;
}
while(--h);
}
}
}
}
return(0);
}
}
/* amiga_copy_color_raw():
*
* Copy a color image (oh well...). This is just the same as the
* copy_mono() routine.
*/
int
amiga_copy_color_raw(gx_device *dev,const UBYTE *base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h)
{
if(y < 0 || x < 0 || w < 0 || h < 0)
return(-1);
else
{
if(w > 0 && h > 0)
{
LONG i,j,modulo = xdev -> rport -> BitMap -> BytesPerRow;
UBYTE *line;
line = xdev -> rport -> BitMap -> Planes[0] + y * xdev -> rport -> BitMap -> BytesPerRow;
w += sourcex;
do
{
for(i = sourcex, j = x ; i < w ; i++, j++)
{
if(base[i >> 3] & shift[i & 7])
line[j >> 3] |= shift[j & 7];
else
line[j >> 3] &= masks[j & 7];
}
base += raster;
line += modulo;
}
while(--h);
}
return(0);
}
}
/* amiga_fill_rectangle_raw():
*
* Fill a rectangular area in a bitmap.
*/
int
amiga_fill_rectangle_raw(gx_device *dev,int x,int y,int w,int h,gx_color_index color)
{
if(x < 0 || x > xdev -> width - w || y < 0 || y > xdev -> height - h)
return(-1);
else
{
if(w > 0 && h > 0 && color != gx_no_color_index)
{
UBYTE *line,startmask,endmask;
LONG right,mid,modulo = xdev -> rport -> BitMap -> BytesPerRow;
right = x + w;
mid = (right >> 3) - (x >> 3);
line = xdev -> rport -> BitMap -> Planes[0] + y * xdev -> rport -> BitMap -> BytesPerRow + (x >> 3);
x &= 7;
right &= 7;
if(color)
{
startmask = 0xFF >> x;
endmask = ~(0xFF >> right);
if(mid)
{
UBYTE *ptr;
int i;
do
{
ptr = line;
*ptr++ |= startmask;
i = mid;
while(--i > 0)
*ptr++ = 0xFF;
*ptr |= endmask;
line += modulo;
}
while(--h);
}
else
{
startmask &= endmask;
do
{
*line |= startmask;
line += modulo;
}
while(--h);
}
}
else
{
startmask = ~(0xFF >> x);
endmask = 0xFF >> right;
if(mid)
{
UBYTE *ptr;
LONG i;
do
{
ptr = line;
*ptr++ &= startmask;
i = mid;
while(--i > 0)
*ptr++ = 0x00;
*ptr &= endmask;
line += modulo;
}
while(--h);
}
else
{
startmask |= endmask;
do
{
*line &= startmask;
line += modulo;
}
while(--h);
}
}
}
return(0);
}
}
/* amiga_draw_line_raw():
*
* Draw a hair line, your basic DDA algorithm;
* keep your fingers crossed.
*/
int
amiga_draw_line_raw(gx_device *dev,int x,int y,int x1,int y1,gx_color_index color)
{
if(color != gx_no_color_index && (x != x1 || y != y1))
{
short xstep,ystep,dx,dy,diff,modulo;
UBYTE *line,*plane,pen;
LONG last;
modulo = xdev -> rport -> BitMap -> BytesPerRow;
plane = xdev -> rport -> BitMap -> Planes[0];
line = &plane[y1 * modulo];
last = y1;
pen = line[x1 >> 3] & (x1 & 7);
dx = x1 - x;
dy = y1 - y;
if(dx < 0)
{
dx = -dx;
dy = -dy;
x = x1;
y = y1;
}
if(y != last)
line = &plane[(last = y) * modulo];
if(color)
{
line[x >> 3] |= shift[x & 7];
xstep = ystep = 0;
if(dy < 0)
{
if(dx > -dy)
{
diff = -dx / 2;
do
{
xstep++;
if(diff > 0)
{
ystep--;
diff = diff - dy - dx;
}
else
diff -= dy;
{
LONG x1 = x + xstep,y1 = y + ystep;
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] |= shift[x1 & 7];
}
}
while(xstep < dx);
}
else
{
if(dx == -dy)
diff = 0;
else
diff = -dy / 2;
do
{
ystep--;
if(diff > 0)
diff -= dx;
else
{
xstep++;
diff = diff - dy - dx;
}
{
LONG x1 = x + xstep,y1 = y + ystep;
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] |= shift[x1 & 7];
}
}
while(ystep > dy);
}
}
else
{
if(dx > dy)
{
diff = -dx / 2;
do
{
xstep++;
if(diff > 0)
{
ystep++;
diff = diff + dy - dx;
}
else
diff += dy;
{
LONG x1 = x + xstep,y1 = y + ystep;
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] |= shift[x1 & 7];
}
}
while(xstep < dx);
}
else
{
if(dx == dy)
diff = 0;
else
diff = dy / 2;
do
{
ystep++;
if(diff > 0)
diff -= dx;
else
{
xstep++;
diff = diff + dy - dx;
}
{
LONG x1 = x + xstep,y1 = y + ystep;
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] |= shift[x1 & 7];
}
}
while(ystep < dy);
}
}
if(!pen)
{
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] &= masks[x1 & 7];
}
}
else
{
line[x >> 3] &= masks[x & 7];
xstep = ystep = 0;
if(dy < 0)
{
if(dx > -dy)
{
diff = -dx / 2;
do
{
xstep++;
if(diff > 0)
{
ystep--;
diff = diff - dy - dx;
}
else
diff -= dy;
{
LONG x1 = x + xstep,y1 = y + ystep;
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] &= masks[x1 & 7];
}
}
while(xstep < dx);
}
else
{
if(dx == -dy)
diff = 0;
else
diff = -dy / 2;
do
{
ystep--;
if(diff > 0)
diff -= dx;
else
{
xstep++;
diff = diff - dy - dx;
}
{
LONG x1 = x + xstep,y1 = y + ystep;
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] &= masks[x1 & 7];
}
}
while(ystep > dy);
}
}
else
{
if(dx > dy)
{
diff = -dx / 2;
do
{
xstep++;
if(diff > 0)
{
ystep++;
diff = diff + dy - dx;
}
else
diff += dy;
{
LONG x1 = x + xstep,y1 = y + ystep;
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] &= masks[x1 & 7];
}
}
while(xstep < dx);
}
else
{
if(dx == dy)
diff = 0;
else
diff = dy / 2;
do
{
ystep++;
if(diff > 0)
diff -= dx;
else
{
xstep++;
diff = diff + dy - dx;
}
{
LONG x1 = x + xstep,y1 = y + ystep;
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] &= masks[x1 & 7];
}
}
while(ystep < dy);
}
}
if(pen)
{
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] |= pen;
}
}
}
return(0);
}
/* amiga_open_ilbm(gx_device *dev):
*
* Open the ilbm device.
*/
int
amiga_open_ilbm(gx_device *dev)
{
if(xdev -> width <= 0 || xdev -> height <= 0)
{
if(xdev -> page_width > 0.0)
xdev -> width = (int)(xdev -> x_pixels_per_inch * xdev -> page_width);
else
xdev -> width = 640;
if(xdev -> page_height > 0.0)
xdev -> height = (int)(xdev -> y_pixels_per_inch * xdev -> page_height);
else
xdev -> height = 512;
}
if(xdev -> rport = (struct RastPort *)AllocVec(sizeof(struct RastPort),MEMF_ANY))
{
InitRastPort(xdev -> rport);
if(xdev -> bitmap = (struct BitMap *)AllocVec(sizeof(struct BitMap),MEMF_ANY))
{
InitBitMap(xdev -> bitmap,1,xdev -> width,xdev -> height);
if(xdev -> bitplane = AllocVec(xdev -> bitmap -> Rows * xdev -> bitmap -> BytesPerRow,MEMF_ANY | MEMF_CLEAR))
{
xdev -> bitmap -> Planes[0] = xdev -> bitplane;
xdev -> rport -> BitMap = xdev -> bitmap;
xdev -> page_count = 1;
DarkPen = 0;
LightPen = 1;
return(0);
}
else
{
char buffer[256];
sprintf(buffer,"Ghostscript: failed to allocate raster (wanted %ld, largest %ld)",xdev -> bitmap -> Rows * xdev -> bitmap -> BytesPerRow,AvailMem(MEMF_ANY | MEMF_LARGEST));
perror(buffer);
}
}
else
perror("Ghostscript: failed to allocate bitmap");
}
else
perror("Ghostscript: failed to allocate raster port");
return(-1);
}
/* amiga_output_page_ilbm(gx_device *dev,int,int):
*
* Send a bitmap to an IFF-ILBM file.
*/
int
amiga_output_page_ilbm(gx_device *dev,int num_copies,int flush)
{
const sigset_t trapped = sigmask(SIGINT);
char buffer[270];
LONG result = -1;
sprintf(buffer,"%s_%04d.ilbm",xdev -> file_name,xdev -> page_count);
fprintf(stdout,"\n\033[ASaving page Nº%d to \"%s\"...\033[K",xdev -> page_count,buffer);
fflush(stdout);
sigprocmask(SIG_BLOCK,&trapped,NULL);
if(SaveBitMap(buffer,xdev -> bitmap,xdev -> width,xdev -> height,(UWORD)xdev -> x_pixels_per_inch,xdev -> y_pixels_per_inch))
{
fprintf(stdout,"\n\033[APage saved to file \"%s\".\033[K\n",buffer);
result = 0;
xdev -> page_count;
}
else
perror("\n\033[AGhostscript: error saving page\033[K");
sigprocmask(SIG_UNBLOCK,&trapped,NULL);
return(result);
}
/* amiga_close_ilbm(gx_device *dev):
*
* Close the ilbm driver.
*/
int
amiga_close_ilbm(gx_device *dev)
{
if(xdev -> bitplane)
{
FreeVec(xdev -> bitplane);
xdev -> bitplane = NULL;
}
if(xdev -> bitmap)
{
FreeVec(xdev -> bitmap);
xdev -> bitmap = NULL;
}
if(xdev -> rport)
{
FreeVec(xdev -> rport);
xdev -> rport = NULL;
}
xdev -> width = xdev -> height = 0;
/* xdev -> x_pixels_per_inch = x_pixels_per_inch = 72.72;*/
return(0);
}
private const gs_prop_item props_amiga[] =
{
prop_def("PageWidth", prt_string),
prop_def("PageHeight", prt_string),
prop_def("OutputFile", prt_string)
};
int
amiga_get_props(gx_device *dev,gs_prop_item *plist)
{
int start = gx_default_get_props(dev,plist);
if(plist != 0)
{
gs_prop_item *pi = plist + start;
memcpy(pi,props_amiga,sizeof(props_amiga));
pi[0] . value .a.p.s = "";
pi[0] . value .a.size = -1;
pi[1] . value .a.p.s = "";
pi[1] . value .a.size = -1;
pi[2] . value .a.p.s = "";
pi[2] . value .a.size = -1;
}
return(start + (sizeof(props_amiga) / sizeof(gs_prop_item)));
}
int
amiga_put_props(gx_device *dev,gs_prop_item *plist,int count)
{
gs_prop_item *known[3];
LONG code = 0;
props_extract(plist,count,props_amiga,3,known,0);
if((code = gx_default_put_props(dev,plist,count)) < 0)
return(code);
else
{
if(known[0] != 0)
{
gs_prop_item *pn = known[0];
LONG size = pn -> value . a . size;
char temp[256];
if(size >= 256)
{
pn -> status = pv_limitcheck;
code = gs_error_limitcheck;
}
else
{
memcpy(temp,pn -> value . a . p . s,size);
temp[size] = 0;
xdev -> page_width = GetInches(temp);
if(xdev -> page_width <= 0.0)
{
xdev -> page_width = 0.0;
pn -> status = pv_limitcheck;
code = gs_error_limitcheck;
}
else
{
if(code == 0)
code = 1;
}
}
}
if(known[1] != 0)
{
gs_prop_item *pn = known[1];
LONG size = pn -> value . a . size;
char temp[256];
if(size >= 256)
{
pn -> status = pv_limitcheck;
code = gs_error_limitcheck;
}
else
{
memcpy(temp,pn -> value . a . p . s,size);
temp[size] = 0;
xdev -> page_height = GetInches(temp);
if(xdev -> page_height <= 0.0)
{
xdev -> page_height = 0.0;
pn -> status = pv_limitcheck;
code = gs_error_limitcheck;
}
else
{
if(code == 0)
code = 1;
}
}
}
if(known[2] != 0)
{
gs_prop_item *pn = known[2];
LONG size = pn -> value . a . size;
if(size >= 256)
{
pn -> status = pv_limitcheck;
code = gs_error_limitcheck;
}
else
{
memcpy(xdev -> file_name,pn -> value . a . p . s,size);
xdev -> file_name[size] = 0;
}
}
if(code < 0)
return_error(code);
if(xdev -> is_open && code)
{
LONG ccode = gs_closedevice(dev);
if(ccode < 0)
return(ccode);
}
return(code);
}
}
/* amiga_color_map_rgb_color(gx_device *dev,gx_color_value red,gx_color_value green,gx_color_value blue):
*
* Turn an RGB colour into a pen index.
*/
gx_color_index
amiga_color_map_rgb_color(gx_device *dev,gx_color_value red,gx_color_value green,gx_color_value blue)
{
LONG max = xdev -> cube_size - 1,r,g,b;
r = (max * red) / gx_max_color_value;
g = (max * green) / gx_max_color_value;
b = (max * blue) / gx_max_color_value;
return((r * xdev -> cube_size + g) * xdev -> cube_size + b);
}
/* amiga_color_map_color_rgb(gx_device *dev,gx_color_index color,gx_color_value rgb[3]):
*
* Turn a pen index into RGB colour values.
*/
int
amiga_color_map_color_rgb(gx_device *dev,gx_color_index color,gx_color_value rgb[3])
{
LONG i,value,max = xdev -> cube_size - 1;
for(i = 2 ; i >= 0 ; i--)
{
value = color % xdev -> cube_size;
rgb[i] = (gx_max_color_value * value) / max;
color /= xdev -> cube_size;
}
return(0);
}
/* amiga_color_map_rgb_color_pen(gx_device *dev,gx_color_value red,gx_color_value green,gx_color_value blue):
*
* Turn an RGB colour into a pen index; this routine takes remapped
* pens into account.
*/
gx_color_index
amiga_color_map_rgb_color_pen(gx_device *dev,gx_color_value red,gx_color_value green,gx_color_value blue)
{
LONG max = xdev -> cube_size - 1,r,g,b;
r = (max * red) / gx_max_color_value;
g = (max * green) / gx_max_color_value;
b = (max * blue) / gx_max_color_value;
return(xdev -> pens[(r * xdev -> cube_size + g) * xdev -> cube_size + b]);
}
/* amiga_color_map_color_rgb_pen(gx_device *dev,gx_color_index color,gx_color_value rgb[3]):
*
* Turn a pen index into RGB colour values; this routine takes remapped
* pens into account.
*/
int
amiga_color_map_color_rgb_pen(gx_device *dev,gx_color_index color,gx_color_value rgb[3])
{
LONG i,value,max = xdev -> cube_size - 1;
/* Find the matching pen... */
for(i = 0 ; i < xdev -> cube_size * xdev -> cube_size * xdev -> cube_size ; i++)
{
if(xdev -> pens[i] == color)
{
color = i;
break;
}
}
for(i = 2 ; i >= 0 ; i--)
{
value = color % xdev -> cube_size;
rgb[i] = (gx_max_color_value * value) / max;
color /= xdev -> cube_size;
}
return(0);
}
/* amiga_copy_color8():
*
* Copy a color image, the source is guaranteed to consist of
* one byte per colour.
*/
int
amiga_copy_color8(gx_device *dev,const UBYTE *base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h)
{
if(y < 0 || x < 0 || w < 0 || h < 0)
return(-1);
else
{
if(w > 0 && h > 0)
{
base += sourcex;
do
{
WritePixelLine8(xdev -> rport,x,y++,w,(UBYTE *)base,xdev -> temp_rport);
base += raster;
}
while(--h);
}
return(0);
}
}
/* amiga_copy_mono_raw_color():
*
* Copy a monochrome image to a bitmap.
*/
int
amiga_copy_mono_raw_color(gx_device *dev,const UBYTE *base,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)
{
if(y < 0 || x < 0 || w < 0 || h < 0)
return(-1);
else
{
if(w > 0 && h > 0 && zero != gx_no_color_index && one != gx_no_color_index)
{
PLANEPTR line[12];
LONG i,j,k,modulo = xdev -> rport -> BitMap -> BytesPerRow,depth = xdev -> rport -> BitMap -> Depth;
for(i = 0 ; i < depth ; i++)
line[i] = xdev -> rport -> BitMap -> Planes[i] + y * modulo;
w += sourcex;
if(zero == gx_no_color_index)
{
do
{
for(i = sourcex, j = x ; i < w ; i++, j++)
{
if(base[i >> 3] & shift[i & 7])
{
for(k = 0 ; k < depth ; k++)
{
if(one & (1 << k))
line[k][j >> 3] |= shift[j & 7];
else
line[k][j >> 3] &= masks[j & 7];
}
}
}
base += raster;
for(k = 0 ; k < depth ; k++)
line[k] += modulo;
}
while(--h);
}
else
{
if(one == gx_no_color_index)
{
do
{
for(i = sourcex, j = x ; i < w ; i++, j++)
{
if(base[i >> 3] & shift[i & 7])
{
for(k = 0 ; k < depth ; k++)
{
if(zero & (1 << k))
line[k][j >> 3] |= shift[j & 7];
else
line[k][j >> 3] &= masks[j & 7];
}
}
}
base += raster;
for(k = 0 ; k < depth ; k++)
line[k] += modulo;
}
while(--h);
}
else
{
do
{
for(i = sourcex, j = x ; i < w ; i++, j++)
{
if(base[i >> 3] & shift[i & 7])
{
for(k = 0 ; k < depth ; k++)
{
if(one & (1 << k))
line[k][j >> 3] |= shift[j & 7];
else
line[k][j >> 3] &= masks[j & 7];
}
}
else
{
for(k = 0 ; k < depth ; k++)
{
if(zero & (1 << k))
line[k][j >> 3] |= shift[j & 7];
else
line[k][j >> 3] &= masks[j & 7];
}
}
}
base += raster;
for(k = 0 ; k < depth ; k++)
line[k] += modulo;
}
while(--h);
}
}
}
return(0);
}
}
/* amiga_copy_color_raw_color16():
*
* Copy a color image, the source data is guaranteed to consist
* of one word per colour.
*/
int
amiga_copy_color_raw_color16(gx_device *dev,const UBYTE *data,int sourcex,int raster,gx_bitmap_id id,int x,int y,int w,int h)
{
if(y < 0 || x < 0 || w < 0 || h < 0)
return(-1);
else
{
if(w > 0 && h > 0)
{
PLANEPTR line[12];
LONG i,j,k,modulo = xdev -> rport -> BitMap -> BytesPerRow,depth = xdev -> rport -> BitMap -> Depth;
UWORD *base = (UWORD *)data;
for(i = 0 ; i < depth ; i++)
line[i] = xdev -> rport -> BitMap -> Planes[i] + y * modulo;
w += sourcex;
raster /= 2;
do
{
for(i = sourcex, j = x ; i < w ; i++, j++)
{
for(k = 0 ; k < depth ; k++)
{
if(base[i] & (1 << k))
line[k][j >> 3] |= shift[j & 7];
else
line[k][j >> 3] &= masks[j & 7];
}
}
base += raster;
for(k = 0 ; k < depth ; k++)
line[k] += modulo;
}
while(--h);
}
return(0);
}
}
/* amiga_fill_rectangle_raw_color():
*
* Fill a rectangular area in a bitmap.
*/
int
amiga_fill_rectangle_raw_color(gx_device *dev,int x,int y,int w,int h,gx_color_index color)
{
if(x < 0 || x > xdev -> width - w || y < 0 || y > xdev -> height - h)
return(-1);
else
{
if(w > 0 && h > 0 && color != gx_no_color_index)
{
PLANEPTR line[12];
LONG i,j,right,mid,modulo = xdev -> rport -> BitMap -> BytesPerRow,depth = xdev -> rport -> BitMap -> Depth;
for(i = 0 ; i < depth ; i++)
line[i] = xdev -> rport -> BitMap -> Planes[i] + y * modulo + (x >> 3);
right = x + w;
mid = (right >> 3) - (x >> 3);
x &= 7;
right &= 7;
if(mid)
{
UBYTE *ptr;
do
{
for(j = 0 ; j < depth ; j++)
{
ptr = line[j];
i = mid;
if(color & (1 << j))
{
*ptr++ |= 0xFF >> x;
while(--i > 0)
*ptr++ = 0xFF;
*ptr |= ~(0xFF >> right);
}
else
{
*ptr++ &= ~(0xFF >> x);
while(--i > 0)
*ptr++ = 0x00;
*ptr &= 0xFF >> right;
}
line[j] += modulo;
}
}
while(--h);
}
else
{
UBYTE one_mask = (0xFF >> x) & ~(0xFF >> right),
zero_mask = ~(0xFF >> x) | (0xFF >> right);
do
{
for(j = 0 ; j < depth ; j++)
{
if(color & (1 << j))
*line[j] |= one_mask;
else
*line[j] &= zero_mask;
line[j] += modulo;
}
}
while(--h);
}
}
return(0);
}
}
/* amiga_draw_line_raw_color():
*
* Draw a hair line, your basic DDA algorithm;
* keep your fingers crossed.
*/
int
amiga_draw_line_raw_color(gx_device *dev,int x,int y,int x1,int y1,gx_color_index color)
{
if(color != gx_no_color_index && (x != x1 || y != y1))
{
LONG xstep,ystep,dx,dy,diff,modulo;
UBYTE *line,*plane,pen;
LONG last,i,orig_x = x,orig_y = y;
modulo = xdev -> rport -> BitMap -> BytesPerRow;
for(i = 0 ; i < xdev -> rport -> BitMap -> Depth ; i++)
{
plane = xdev -> rport -> BitMap -> Planes[i];
line = &plane[y1 * modulo];
last = y1;
pen = line[x1 >> 3] & (x1 & 7);
x = orig_x;
y = orig_y;
dx = x1 - x;
dy = y1 - y;
if(dx < 0)
{
dx = -dx;
dy = -dy;
x = x1;
y = y1;
}
if(y != last)
line = &plane[(last = y) * modulo];
if(color & (1 << i))
{
line[x >> 3] |= shift[x & 7];
xstep = ystep = 0;
if(dy < 0)
{
if(dx > -dy)
{
diff = -dx / 2;
do
{
xstep++;
if(diff > 0)
{
ystep--;
diff = diff - dy - dx;
}
else
diff -= dy;
{
LONG x1 = x + xstep,y1 = y + ystep;
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] |= shift[x1 & 7];
}
}
while(xstep < dx);
}
else
{
if(dx == -dy)
diff = 0;
else
diff = -dy / 2;
do
{
ystep--;
if(diff > 0)
diff -= dx;
else
{
xstep++;
diff = diff - dy - dx;
}
{
LONG x1 = x + xstep,y1 = y + ystep;
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] |= shift[x1 & 7];
}
}
while(ystep > dy);
}
}
else
{
if(dx > dy)
{
diff = -dx / 2;
do
{
xstep++;
if(diff > 0)
{
ystep++;
diff = diff + dy - dx;
}
else
diff += dy;
{
LONG x1 = x + xstep,y1 = y + ystep;
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] |= shift[x1 & 7];
}
}
while(xstep < dx);
}
else
{
if(dx == dy)
diff = 0;
else
diff = dy / 2;
do
{
ystep++;
if(diff > 0)
diff -= dx;
else
{
xstep++;
diff = diff + dy - dx;
}
{
LONG x1 = x + xstep,y1 = y + ystep;
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] |= shift[x1 & 7];
}
}
while(ystep < dy);
}
}
if(!pen)
{
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] &= masks[x1 & 7];
}
}
else
{
line[x >> 3] &= masks[x & 7];
xstep = ystep = 0;
if(dy < 0)
{
if(dx > -dy)
{
diff = -dx / 2;
do
{
xstep++;
if(diff > 0)
{
ystep--;
diff = diff - dy - dx;
}
else
diff -= dy;
{
LONG x1 = x + xstep,y1 = y + ystep;
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] &= masks[x1 & 7];
}
}
while(xstep < dx);
}
else
{
if(dx == -dy)
diff = 0;
else
diff = -dy / 2;
do
{
ystep--;
if(diff > 0)
diff -= dx;
else
{
xstep++;
diff = diff - dy - dx;
}
{
LONG x1 = x + xstep,y1 = y + ystep;
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] &= masks[x1 & 7];
}
}
while(ystep > dy);
}
}
else
{
if(dx > dy)
{
diff = -dx / 2;
do
{
xstep++;
if(diff > 0)
{
ystep++;
diff = diff + dy - dx;
}
else
diff += dy;
{
LONG x1 = x + xstep,y1 = y + ystep;
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] &= masks[x1 & 7];
}
}
while(xstep < dx);
}
else
{
if(dx == dy)
diff = 0;
else
diff = dy / 2;
do
{
ystep++;
if(diff > 0)
diff -= dx;
else
{
xstep++;
diff = diff + dy - dx;
}
{
LONG x1 = x + xstep,y1 = y + ystep;
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] &= masks[x1 & 7];
}
}
while(ystep < dy);
}
}
if(pen)
{
if(y1 != last)
line = &plane[(last = y1) * modulo];
line[x1 >> 3] |= pen;
}
}
}
}
return(0);
}